嗯,这个问题几乎说明了一切.使用JPARepository,我如何更新实体?

JPARepository只有一个save方法,它没有告诉我它实际上是在创建还是在更新.例如,我向数据库用户插入一个简单的对象,它有三个字段:firstnamelastnameage:

 @Entity
 public class User {

  private String firstname;
  private String lastname;
  //Setters and getters for age omitted, but they are the same as with firstname and lastname.
  private int age;

  @Column
  public String getFirstname() {
    return firstname;
  }
  public void setFirstname(String firstname) {
    this.firstname = firstname;
  }

  @Column
  public String getLastname() {
    return lastname;
  }
  public void setLastname(String lastname) {
    this.lastname = lastname;
  }

  private long userId;

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  public long getUserId(){
    return this.userId;
  }

  public void setUserId(long userId){
    this.userId = userId;
  }
}

然后我简单地调用save(),这实际上是对数据库的插入:

 User user1 = new User();
 user1.setFirstname("john"); user1.setLastname("dew");
 user1.setAge(16);

 userService.saveUser(user1);// This call is actually using the JPARepository: userRepository.save(user);

到现在为止,一直都还不错.现在我想更新这个用户,比如改变他的年龄.为此,我可以使用QueryDSL或NamedQuery之类的查询.但是,考虑到我只想使用spring数据jpa和JPARepository,我该如何告诉它,我想进行更新,而不是插入?

具体来说,我如何告诉spring data jpa,具有相同用户名和名字的用户实际上是平等的,并且应该更新现有实体?压倒平等并不能解决这个问题.

推荐答案

实体的标识由其主键定义.因为firstnamelastname不是主键的一部分,所以如果Userlastname有不同的userId,你不能告诉JPA将它们视为相同的firstnamelastname.

所以,如果你想更新由firstnamelastname标识的User,你需要通过查询找到User,然后更改找到的对象的相应字段.这些更改将在事务结束时自动刷新到数据库中,这样您就不需要做任何事情来显式保存这些更改.

EDIT:

也许我应该详细说明JPA的整体语义.设计持久性API有两种主要方法:

  • insert/update approach.当你需要修改数据库时,你应该显式地调用持久化API的方法:你调用insert来插入一个对象,或者调用update来将对象的新状态保存到数据库中.

  • Unit of Work approach美元.在本例中,您有一组持久化库的对象managed.您对这些对象所做的所有更改将在工作单元结束时(通常情况下是在当前事务结束时)自动刷新到数据库.当您需要向数据库插入新记录时,您可以创建相应的对象managed.Managed个对象由它们的主键标识,所以如果您用预定义的主键managed创建一个对象,它将与具有相同id的数据库记录相关联,并且该对象的状态将自动传播到该记录.

JPA遵循后一种方法.save() in-Spring数据JPA由merge() in-plain JPA支持,因此它使您的实体managed如上所述.这意味着,对具有预定义id的对象调用save()将更新相应的数据库记录,而不是插入新记录,这也解释了为什么不调用save().

Java相关问答推荐

Java SSLocket查明客户端是否发送了证书

将状态栏和导航栏设置为白色,带有深色文本

Java字符串常数池困惑

如何使用CSS为选定但未聚焦的表格行设置背景 colored颜色 ?

@从类文件中删除JsonProperty—Java

使用Spring Boot3.2和虚拟线程的并行服务调用

Kotlin内联互操作:强制装箱

具有阻塞方法的开源库是否应该为执行提供异步选项?

SonarLint:只能有条件地调用方法(S)

声明MessageChannel Bean的首选方式

如何在太阳系模拟器中添加月球?

X=x*0.90;产生有损转换误差.X*=0.90;不是.为什么?

我该如何为我的类编写getter和setter方法?

为什么我的登录终结点不能被任何请求访问?

Bash数组的单引号元素并使用空格连接

读取ConcurrentHashMap中的可变对象

Java泛型方法重载

java中的网上购物车解析错误

如何使用命令行为Java应用程序生成烟雾测试用例

OpenAPI Maven插件生成错误的Java接口名称