Spring JPA版本化实体休眠错误
除了捕获异常并重试之外,还有更好的方法更新版本化实体吗? 下面是代码Spring JPA版本化实体休眠错误,spring,hibernate,spring-data-jpa,Spring,Hibernate,Spring Data Jpa,除了捕获异常并重试之外,还有更好的方法更新版本化实体吗? 下面是代码 @Entity @AllArgsConstructor @Builder @NoArgsConstructor @Data @IdClass(com.test.domain.EmployeeKey.class) public class Employee { @Id private Integer employeeId; private String name; private Double c
@Entity
@AllArgsConstructor
@Builder
@NoArgsConstructor
@Data
@IdClass(com.test.domain.EmployeeKey.class)
public class Employee {
@Id
private Integer employeeId;
private String name;
private Double commission;
@Id
private LocalDate inputDate;
@Version
private Integer version;
}
public class EmployeeKey implements Serializable {
private Integer employeeId;
private java.time.LocalDate inputDate;
}
@SpringBootApplication
@Slf4j
public class SampleApplication {
public static void main(final String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
@Component
public class AppStartupRunner implements ApplicationRunner {
@Autowired
EmployeeRepo employeeRepo;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("Your application started with option names : {}", args.getOptionNames());
List<Employee> empList = new ArrayList();
Employee employeeComm1 = Employee.builder().employeeId(1).name("Sam").commission(100.45).inputDate(LocalDate.of(2019,10,01)).build();
Employee employeeComm2 = Employee.builder().employeeId(1).name("Sam").commission(87.54).inputDate(LocalDate.of(2019,10,01)).build();
Employee employeeComm3 = Employee.builder().employeeId(2).name("John").commission(56.78).inputDate(LocalDate.of(2019,10,01)).build();
Employee employeeComm4 = Employee.builder().employeeId(3).name("Katie").commission(65.23).inputDate(LocalDate.of(2019,10,01)).build();
empList.add(employeeComm1);
empList.add(employeeComm3);
empList.add(employeeComm4);
empList.add(employeeComm2);
// employeeRepo.saveAll(empList);
for (Employee emp: empList) {
try {
employeeRepo.save(emp);
}
catch(Exception e) {
if (employeeRepo.findByEmployeeIdAndInputDate(emp.getEmployeeId(), emp.getInputDate()).isPresent()) {
Employee empFromDb = employeeRepo.findByEmployeeIdAndInputDate(emp.getEmployeeId(), emp.getInputDate()).get();
empFromDb.setCommission(emp.getCommission());
empFromDb.setName(emp.getName());
employeeRepo.save(empFromDb);
}
}
}
}
}
}
@实体
@AllArgsConstructor
@建筑商
@诺尔格构装师
@资料
@IdClass(com.test.domain.EmployeeKey.class)
公营雇员{
@身份证
私有整数employeeId;
私有字符串名称;
私人双重佣金;
@身份证
私有LocalDate输入日期;
@版本
私有整数版本;
}
公共类EmployeeKey实现可序列化{
私有整数employeeId;
私有java.time.LocalDate inputDate;
}
@SpringBoot应用程序
@Slf4j
公共类抽样应用程序{
公共静态void main(最终字符串[]args){
run(SampleApplication.class,args);
}
@组成部分
公共类AppStartupRunner实现ApplicationRunner{
@自动连线
EmployeeRepo EmployeeRepo;
@凌驾
公共void运行(ApplicationArguments参数)引发异常{
log.info(“您的应用程序以选项名开始:{}”,args.getOptionNames());
List empList=new ArrayList();
Employee employeeComm1=Employee.builder().employeeId(1).name(“Sam”).commission(100.45).inputDate(LocalDate.of(2019,10,01)).build();
Employee employeeComm2=Employee.builder().employeeId(1).name(“Sam”).commission(87.54).inputDate(LocalDate.of(2019,10,01)).build();
Employee employeeComm3=Employee.builder().employeeId(2).姓名(“John”).佣金(56.78).输入日期(LocalDate.of(2019,10,01)).build();
Employee employeeComm4=Employee.builder().employeeId(3).姓名(“Katie”).佣金(65.23).输入日期(LocalDate.of(2019,10,01)).build();
添加(employeeComm1);
添加(employeeComm3);
添加(employeeComm4);
添加(employeeComm2);
//employeeRepo.saveAll(employist);
for(员工emp:员工列表){
试一试{
雇员储蓄(emp);
}
捕获(例外e){
if(employeeRepo.findByEmployeeIdAndInputDate(emp.getEmployeeId(),emp.getInputDate()).isPresent()){
Employee empFromDb=employeeRepo.findbyeemployeeidandInputDate(emp.getEmployeeId(),emp.getInputDate()).get();
empFromDb.setCommission(emp.getCommission());
empFromDb.setName(emp.getName());
employeeRepo.save(empFromDb);
}
}
}
}
}
}
输出如下所示
Hibernate:在员工(佣金、姓名、版本、员工id、输入日期)中插入值(?,,,?,?)
Hibernate:在员工(佣金、姓名、版本、员工id、输入日期)中插入值(?,,,?,?)
Hibernate:在员工(佣金、姓名、版本、员工id、输入日期)中插入值(?,,,?,?)
Hibernate:在员工(佣金、姓名、版本、员工id、输入日期)中插入值(?,,,?,?)
2019-10-15 16:43:10.372警告17216---[main]o.h.engine.jdbc.spi.SqlExceptionHelper:SQL错误:1,SQLState:23000
2019-10-15 16:43:10.372错误17216---[main]o.h.engine.jdbc.spi.SqlExceptionHelper:ORA-00001:违反了唯一约束(I706446.SYS_C008493)
休眠:选择employee0.employee0.id作为EmployeeID1\u 0,employee0.input\u date作为input\u date 2\u 0,employee0.commission作为佣金3\u 0,employee0.name作为名称4\u 0,employee0.version作为版本5\u来自employee0,其中employee0.employee0\u id=?和雇员0。输入日期=?
休眠:选择employee0.employee0.id作为EmployeeID1\u 0,employee0.input\u date作为input\u date 2\u 0,employee0.commission作为佣金3\u 0,employee0.name作为名称4\u 0,employee0.version作为版本5\u来自employee0,其中employee0.employee0\u id=?和雇员0。输入日期=?
休眠:选择employee0。employee0。id作为EmployeeID1。0。0。0。employee0。输入日期作为输入日期2。0。0。佣金作为佣金3。0。0。employee0。名称作为名称4。0。0。版本作为版本5。0。来自employee0。其中employee0。employee0。id=?和雇员0。输入日期=?
Hibernate:更新员工集佣金=?,名称=?,版本=?其中employee_id=?并输入_date=?和版本=
我希望hibernate发布版本列的更新
递增
你的期望是错误的。您使用的版本与预期不同。版本控制的目的是提供乐观锁定,而不仅仅是指示实体更改了多少次。预期的使用场景如下:在更新实体之前,您应该从数据库中读取它,然后修改,然后保存。Hibernate检查您试图保存的版本是否与数据库中的版本相同
A) 如果相同,它将自动增加版本并保存实体,即更新数据库中的现有记录
B) 如果您试图保存的实体中的版本低于数据库中的版本,则表示您正在尝试保存过时的版本。这意味着您不知道在此期间所做的更改。在这种情况下,Hibernate将引发异常。如果员工存在,您是否正在更新现有员工?是的,如果员工ID+inputDate的组合存在-我希望Hibernate在DB表中发出版本列递增的更新。我的方法是先检查数据库中是否存在该实体。如果是的话,我会更新它。否则我会创造它。