【问题标题】:Spring JPA Versioned Entity hibernate errorsSpring JPA 版本化实体休眠错误
【发布时间】:2020-02-12 14:18:47
【问题描述】:

除了捕获异常和重试之外,还有更好的方法来更新版本化实体吗? 下面是代码

@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);
                     }

                }
            }

        }
    }
}

输出如下所示 Hibernate:插入员工(commission、name、version、employee_id、input_date)值(?、?、?、?、?) Hibernate:插入员工(commission、name、version、employee_id、input_date)值(?、?、?、?、?) Hibernate:插入员工(commission、name、version、employee_id、input_date)值(?、?、?、?、?) Hibernate:插入员工(commission、name、version、employee_id、input_date)值(?、?、?、?、?) 2019-10-15 16:43:10.372 WARN 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_.employee_id 作为employee_id1_0_,employee0_.input_date 作为input_date2_0_,employee0_.commission 作为commission3_0_,employee0_.name 作为name4_0_,employee0_.version 作为version5_0_,其中employee0_.employee_id=?和employee0_.input_date=? 休眠:从员工employee0_中选择employee0_.employee_id 作为employee_id1_0_,employee0_.input_date 作为input_date2_0_,employee0_.commission 作为commission3_0_,employee0_.name 作为name4_0_,employee0_.version 作为version5_0_,其中employee0_.employee_id=?和employee0_.input_date=? 休眠:从员工employee0_中选择employee0_.employee_id 作为employee_id1_0_0_,employee0_.input_date 作为input_date2_0_0_,employee0_.commission 作为commission3_0_0_,employee0_.name 作为name4_0_0_,employee0_.version 作为version5_0_0_ 其中employee0_.employee_id=?和employee0_.input_date=? Hibernate:更新员工集commission=?、name=?、version=?哪里employee_id=?和 input_date=?和版本=?

【问题讨论】:

  • 如果员工存在,您是否更新现有员工?
  • 是的,如果employeeId+inputDate 的组合存在 - 我希望休眠发布更新,其中版本列在数据库表中递增。
  • 我的方法是首先检查实体是否存在于数据库中。如果是这样,我会更新它。否则我会创建它。

标签: spring hibernate spring-data-jpa


【解决方案1】:

我希望 hibernate 发布带有版本列的更新 递增

您的预期不正确。您使用的版本与预期使用的版本不同。版本控制的目的是提供乐观锁定,而不是简单地指出实体更改了多少次。预期的使用场景如下:在更新实体之前,您应该从数据库中读取它,然后修改,然后保存。 Hibernate 会检查您尝试保存的版本是否与数据库中的版本相同。

A) 如果相同,它将自动增加版本并保存您的实体,即它将更新数据库中的现有记录。

B) 如果您尝试保存的实体中的版本低于数据库中的版本,则表示您尝试保存的是过时的版本。这意味着您不知道同时进行的更改。在这种情况下,Hibernate 会抛出异常。

【讨论】:

    猜你喜欢
    • 2012-04-19
    • 1970-01-01
    • 2012-07-30
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多