У меня есть проект, полученный из Jhipster, то есть SpringBoot с JPA и Hibernate. По некоторым причинам я должен реализовать постоянство на БД PostgreSQL, используя entityManager и код SQL напрямую.
У меня обычный контроллер покоя:
@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 выполняет обновление дважды, в то время как вставка, кажется, работает хорошо ...