Весенняя загрузка отличается в режиме гибернации от eclipselink

#spring #spring-boot #hibernate #eclipselink

Вопрос:

Я пытаюсь перейти с режима гибернации на Eclipselink в качестве поставщика Jpa для весенней загрузки. Тем не менее, я вижу некоторую разницу в поведении между ними.

Конфигурация Eclipselink

 package com.test.test2;  import org.eclipse.persistence.config.PersistenceUnitProperties; import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.context.annotation.Configuration; import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter; import org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter; import org.springframework.transaction.jta.JtaTransactionManager; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map;  @Configuration public class EclipselinkJpaConfiguration extends JpaBaseConfiguration {  protected EclipselinkJpaConfiguration(DataSource dataSource, JpaProperties   properties, ObjectProviderlt;JtaTransactionManagergt; jtaTransactionManager) {  super(dataSource, properties, jtaTransactionManager); }  @Override protected AbstractJpaVendorAdapter createJpaVendorAdapter() {  return new EclipseLinkJpaVendorAdapter(); }  @Override protected Maplt;String, Objectgt; getVendorProperties() {  Maplt;String, Objectgt; map = new HashMaplt;String, Objectgt;();  map.put(PersistenceUnitProperties.WEAVING, "false");  return map; }  }  

Контроллер

 package com.test.test2;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*;  @RestController  public class PersonController {  @Autowired PersonService personService;  @GetMapping("/test") public ResponseEntitylt;Stringgt; test() {  return new ResponseEntitylt;Stringgt;(personService.helloWorld(), HttpStatus.OK); }  @PostMapping("/createNewPerson") public ResponseEntitylt;Persongt; createNewPerson() {  Person res = personService.createNewPerson();  return new ResponseEntitylt;Persongt;(res, HttpStatus.OK); }  @PostMapping("/updatePerson/{id}") public ResponseEntitylt;Persongt; updatePerson(@PathVariable("id") Long id) {  Person res = personService.updatePerson(id);  personService.transAnnotation();  return new ResponseEntitylt;Persongt;(res, HttpStatus.OK);  } }  

Service

 package com.test.test2;   import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;  import java.util.Optional;  @Service public class PersonService {  @Autowired PersonRepository personRepository;  public String helloWorld() {  return "Hello World!"; }  public Person createNewPerson () {  Person newPerson = new Person();  newPerson.setFirstName("firstName");  newPerson.setLastName("lastName");  return personRepository.save(newPerson); }  public Person updatePerson(Long id) {  Optionallt;Persongt; personOP = personRepository.findById(id);  if (personOP.isPresent()) {  Person person = personOP.get();  person.setFirstName("Update Name");  }   return null; }  @Transactional(readOnly = true) public void transAnnotation () {  } }  

Repository

 package com.test.test2;  import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository;  @Repository public interface PersonRepository extends JpaRepositorylt;Person, Longgt;{ }  

Eclipselink behavior
When calling /updatePerson/{id} api, person.firstName is updated to db without calling personRepoitory.save() if the next method is tagged with @Transactional. As spring repository itself is transactional, even calling a personRepository.findAll() will commit and firstName is updated to db.

Logs

2021-11-24 12:01:06.264 ИНФОРМАЦИЯ 2868 — — — [ основной] o.s.b. w.встроенный.кот.TomcatWebServer : Tomcat с начала на порт(ы): 8081 (HTTP) для связи с пути »
2021-11-24 12:01:06.269 информация 2868 — [ основной] COM и.тест.условие_2.Test2Application : начал Test2Application в 1.966 секунд (JVM, работающей на 2.227)
2021-11-24 12:01:12.689 информация 2868 — [НИО-8081-Exec и-2] о.есть.гр.гр.Гр.[Котяра].[localhost].[/] : Инициализация весеннего ДиспетчерсЕрвлета ‘DispatcherServlet’
2021-11-24 12:01:12.689 ИНФОРМАЦИЯ 2868 — [nio-8081-exec-2] o.s.веб-сервлет.Диспетчер-сервлет : Инициализация сервлета «Диспетчер-сервлет»
2021-11-24 12:01:12.689 ИНФОРМАЦИЯ 2868 — [nio-8081-exec-2] o.s.веб-сервлет.DispatcherServlet : инициализация завершена за 0 мс
[Эл Изобразительное]: в SQL: 2021-11-24 12:01:12.741—ServerSession(2122837918)—связь(555991754)—выберите ID, имя, фамилия от TBL_PERSON где а (ID = ?) персонализация =gt; [1]
[Эл Изобразительное]: в SQL: 2021-11-24 12:01:12.771—ClientSession(1084235622)—связь(819605412)—обновления TBL_PERSON установить «имя»= ? ГДЕ (ID = ?) привязка =gt; [Имя обновления, 1]

В то время как для режима гибернации изменения не передаются в БД, если не вызвана функция сохранения (). Я знаю, что если функция помечена @Transactional, нам не нужно вызывать функцию save (), так как она автоматически зафиксирует изменения. Однако в настоящее время он помечен только в следующем вызываемом методе.

Какие-либо возможные причины этого? Может ли это быть связано с неправильной конфигурацией?

Комментарии:

1. Режим гибернации действует так же и является результатом шаблона «Открыть сеанс в представлении». Отключите это. Кроме того, зачем переходить из режима гибернации в режим EclipseLink? Я обнаружил, что значения спящего режима лучше, чем EclipseLink. Наконец, удалите @Repository из интерфейса, он ничего не добавляет.

2. Это может быть вызвано рядом причин, в основном связанных с весенней гибернацией вне контрактов JPA. У вас есть набор транзакций(только для чтения = true), который(в основном) используется в Hibernate только для возврата отсоединенных экземпляров — spring также не подключал это к другим поставщикам JPA и должен связывать существующий EntityManager с более поздними переходами вместо того, чтобы закрывать его и получать новый — или по какой-то причине фиксирует транзакцию только для чтения вместо отката.