我正在使用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.DefaultNamingStrategy
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
答案 0 :(得分:2)
主要关注的是不要强制开发人员通过调用findOne()然后合并两个对象然后调用save()来显式处理更新操作。
由于Spring数据不支持开箱即用,我需要将此功能添加到我们的API平台。
首先,我尝试扩展JpaRepository的行为以覆盖save()方法。但作为一个接口,我无法更新此行为。
我最终创建了一个EntityMergingService,它接受两个实体,一个来自DB,另一个来自Memory。然后它使用反射来进行空检查并进行合并。
来电方负责调用findOne(),从上述服务调用merge,然后调用save()。
这样,我们就不必为每个实体编写多个合并方法。这不是最好的方法,如果我可以从JPA Repository覆盖save()方法,那会更好。这将在内部执行,findOne(),以及合并和保存合并对象。
答案 1 :(得分:0)
要“更新”实体,您必须:
Branch branch = branchRepo.findOne("12345");
branch.setName("Updated Name");
branch.setAddress("Updated Address");
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.