Spring启动CrudRepo Save()方法没有合并现有的条目,但它正在取代

时间:2017-08-01 10:24:15

标签: hibernate spring-boot spring-data-jpa

我正在使用Spring启动Mysql。每当我从CrudRepository调用save方法时,它都会从表中替换实体。我希望它合并表中现有实体中的新实体。

我在这里做错了什么?

例如。在DB中输入:id = 12345,firstName = foo,lastName = bar

使用新实体调用save:id = 12345,firstName = doe

保存操作后,db有,id = 12345,firstName = doe, lastName = null

我的实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity

public class Branch {
    @Id
    @Column(name = "id")
    private String id;

    @Column(name = "name")
    private String name;

    @Column(name = "address")
    private String address;

    @Column(name = "latitude")
    private String latitude;

    @Column(name = "longitude")
    private String longitude;

    @Column(name = "email")
    private String email;

    @Column(name = "phone")
    private String phone;

    @Enumerated(EnumType.STRING)
    private BranchType branchType;
}

我的回购:

public interface BranchRepo extends CrudRepository<Branch, String> {

}

application.properties

spring.jpa.hibernate.ddl-auto=update
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://mysql-url
spring.datasource.username=user-name-here
spring.datasource.password=password-name-here
spring.jpa.show-sql = true
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.Defau‌​ltNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.use_sql_comments=true 
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.type=trace

2 个答案:

答案 0 :(得分:2)

主要关注的是不要强制开发人员通过调用findOne()然后合并两个对象然后调用save()来显式处理更新操作。

由于Spring数据不支持开箱即用,我需要将此功能添加到我们的API平台。

首先,我尝试扩展JpaRepository的行为以覆盖save()方法。但作为一个接口,我无法更新此行为。

我最终创建了一个EntityMergingService,它接受两个实体,一个来自DB,另一个来自Memory。然后它使用反射来进行空检查并进行合并。

来电方负责调用findOne(),从上述服务调用merge,然后调用save()。

这样,我们就不必为每个实体编写多个合并方法。这不是最好的方法,如果我可以从JPA Repository覆盖save()方法,那会更好。这将在内部执行,findOne(),以及合并和保存合并对象。

答案 1 :(得分:0)

要“更新”实体,您必须:

  1. 从DB中检索:
  2. Branch branch = branchRepo.findOne("12345");
    
    1. 更新其字段:
    2. branch.setName("Updated Name");
      branch.setAddress("Updated Address");
      
      1. 保存此实体:
      2. branchRepo.save(branch);
        

        <强>更新

        如果您不想这样,可以使用“modifying queries”。这样,您必须在每个查询中定义一组更新的字段:

        @Modifying(clearAutomatically = true)
        @Query("update Branch b set b.name = ?1 where b.id = ?2")
        int updateName(String name, String id);
        
        @Modifying(clearAutomatically = true)
        @Query("update Branch b set b.name = ?1, b.address = ?2 where b.id = ?3")
        int updateNameAndAddress(String name, Address address, String id);
        
        // etc.
        
相关问题