我有一个来自Jhipster的项目,即带有JPA和Hibernate的SpringBoot。由于某些原因,我必须直接使用entityManager和SQL代码在PostgreSQL数据库上实现持久性。
我有一个普通的休息控制器:
@GetMapping("/enterprises/{vat}")
public ResponseEntity<Enterprise> getEnterpriseByVat(...
呼叫:
Optional<Enterprise> enterpriseDTO = enterpriseService.findEnterprise(vat, vatRequestBean);
所以这里是EnterpriseService:
public interface EnterpriseService {
Optional<Enterprise> findEnterprise(String vat, VatRequestBean vatRequestBean);
其实现:
@Service
@Transactional
public class EnterpriseServiceImpl implements EnterpriseService {
private final EnterpriseRepository enterpriseRepository;
public EnterpriseServiceImpl(EnterpriseRepository enterpriseRepository) {
this.enterpriseRepository = enterpriseRepository;
}
@Override
public Optional<Enterprise> findEnterprise(String vat, VatRequestBean vatRequestBean) {
return enterpriseRepository.findEnterprise(vat, vatRequestBean);
}
在存储库方面,我有:
@Repository
public interface EnterpriseRepository extends JpaRepository<RequestCache, Long>, EnterpriseRepositoryCustom {}
}
使用自定义存储库:
public interface EnterpriseRepositoryCustom {
Optional<Enterprise> findEnterprise(String vat, VatRequestBean vatRequestBean);
}
最后是实现:
@Repository
@Transactional(readOnly = true)
public class EnterpriseRepositoryImpl implements EnterpriseRepositoryCustom {
@PersistenceContext
EntityManager entityManager;
@Autowired
RestTemplate restTemplate;
...
private void saveRequestCache(RequestCache requestCache) {
if (requestCache.getId() != null) {
entityManager.createNativeQuery(
"update enterprises_data.requests_cache set " +
"vat = ? ," +
"json_data = ? ," +
"request_result = ? ," +
"stack_trace_error = ? ," +
"last_update_user = ? ," +
"last_update_application = ? " +
"where Id_requests_cache = ? ")
.setParameter(1, requestCache.getVat())
.setParameter(2, requestCache.getJsonData())
.setParameter(3, requestCache.getRequestResult())
.setParameter(4, requestCache.getStackTraceError())
.setParameter(5, requestCache.getLastUpdateUser())
.setParameter(6, requestCache.getLastUpdateApplication())
.setParameter(7, requestCache.getId())
.executeUpdate();
} else {
entityManager.createNativeQuery(
"insert into enterprises_data.requests_cache (" +
"json_data, vat, inserting_application, last_update_application, request_result, " +
"stack_trace_error, inserting_user, last_update_user) " +
"values (?,?,?,?,?,?,?,?) ")
.setParameter(1, requestCache.getJsonData())
.setParameter(2, requestCache.getVat())
.setParameter(3, requestCache.getInsertingApplication())
.setParameter(4, requestCache.getInsertingApplication())
.setParameter(5, requestCache.getRequestResult())
.setParameter(6, requestCache.getStackTraceError())
.setParameter(7, requestCache.getInsertingUser())
.setParameter(8, requestCache.getInsertingUser())
.executeUpdate();
}
}
逻辑很简单:保存第一次,更新第二次。实体为:
@Entity
@Table(name = "requests_cache", schema = "enterprises_data")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class RequestCache implements Serializable {
@Id
@Column(name = "id_requests_cache")
private Long id;
@Column(name = "vat")
private String vat;
@Column(name = "json_data")
private String jsonData;
. . .
奇怪的是,插入时似乎createNativeQuery
正好执行以下查询:
"insert into enterprises_data.requests_cache (" +
"json_data, vat, inserting_application, last_update_application, request_result, " +
"stack_trace_error, inserting_user, last_update_user) " +
"values (?,?,?,?,?,?,?,?) "
日志确认:
Hibernate: insert into enterprises_data.requests_cache (json_data, vat, inserting_application, last_update_application, request_result, stack_trace_error, inserting_user, last_update_user) values (?,?,?,?,?,?,?,?)
但是在更新JPA时会执行此操作:
"update enterprises_data.requests_cache set " +
"vat = ? ," +
"json_data = ? ," +
"request_result = ? ," +
"stack_trace_error = ? ," +
"last_update_user = ? ," +
"last_update_application = ? " +
"where Id_requests_cache = ? "
仅次于一个作为日志报告(请注意第二个'set vat =?'的开头,第一个具有所有字段在列表中):
Hibernate: update enterprises_data.requests_cache set inserting_application=?, inserting_date=?, inserting_user=?, json_data=?, last_update_application=?, last_update_date=?, last_update_user=?, request_result=?, stack_trace_error=?, vat=? where id_requests_cache=?
Hibernate: update enterprises_data.requests_cache set vat = ? ,json_data = ? ,request_result = ? ,stack_trace_error = ? ,last_update_user = ? ,last_update_application = ? where Id_requests_cache = ?
所以我无法弄清楚为什么JPA在插入似乎可以正常工作的同时执行两次更新...