Как снять с прокси дочерние объекты из потомка org.springframework.data.repository.CrudRepository - PullRequest
0 голосов
/ 01 февраля 2019

Я создал отношение «многие ко многим» пользователей к проектам в базе данных MySQL и использовал hbm2java (инструмент гибернации для генерации классов Java из таблиц базы данных).Поскольку я использую плагин gradle org.hibernate.gradle.tools.Schema, у меня нет файла hibernate.cfg.xml.

. Я могу получить и правильно распечатать список пользователей из моего потомка CrudRepository<User,Long> (см. Мой код ниже), и каждый пользовательский объект имеет функцию getProjects().Когда я пытаюсь выполнить итерации проектов, принадлежащих пользователю, я получаю эту ошибку:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.xyz.dbmodel.orm.User.projects, could not initialize proxy - no Session

Я хочу придерживаться подхода ленивой загрузки по умолчанию, используемого Java-кодом, сгенерированным hbm2java.

Я пытался позвонить Hibernate.Initialize(user.getProjects()) (как обсуждено на https://howtodoinjava.com/hibernate/use-hibernate-initialize-to-initialize-proxycollection/), но я все еще получаю ту же ошибку, когда пытаюсь выполнить

for(Project project : user.getProjects()) {... }

Все примеры, которые я могнайти, кажется, предположить, что я мог бы выполнить выше для цикла и разархивировать каждый проект. Я не могу.

Вот мой репозиторий:

import org.springframework.data.repository.CrudRepository;
import com.xyz.dataservice.dbmodel.orm.User;
public interface UserRepository extends CrudRepository<User, Long> {}

Здесь я создаю репозиторий:

@Autowired com.xyz.repository.UserRepository userRepository;

Здесь я успешно извлекаю список пользователей

Iterable<User> users = userRepository.findAll();
for(User user : users) {
   log.info("User="+user.getName()); // this works!
   Set<Project> projects = user.getProjects();
   for(Project p : projects) // Error happens here!
   {
      log.info("  project="+p.getName());
   }
 }

Ожидаемые результаты: я получаю список проектов для каждого пользователя. Фактические результаты являются исключением org.hibernate.LazyInitializationException.

Спасибо!

Фев 02 2019 Утреннее обновление

Относительно конфигурации Hibernate

Я не уверен, что вы имеете в виду. Мой плагин gradle генерирует этот файл hibernate.cfg.XML-файл:

 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE hibernate-configuration 
     SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 <hibernate-configuration>
   <session-factory>
     <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
     <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
     <property name="hibernate.connection.url">jdbc:mysql://localhost:3306</property>
     <property name="hibernate.connection.username">searchapp_user</property>
     <property name="hibernate.connection.password">secret</property>
     <property name="hibernate.current_session_context_class">thread</property>
     <property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>
   </session-factory>
 </hibernate-configuration>

Добавление транзакции

Я добавил org.springframework.transaction.annotation.Transactional к новой функции, которую я вызываю

@Transactional
public int fetchUsers() {
    Iterable<User> users = userRepository.findAll();
    return listUsers(users, "");
}

Когда это не помогло, я попытался расширить свой репозиторий с помощью атрибута Transactional:

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
  @Transactional
  public List<User> findAll();
}

Черт, это тоже не помогло.Я заметил эту странную запись в акрах записей журнала.Что это значит?

 2019-02-01 10:50:42.285  INFO 5096 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$6c9c1be1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

Еще раз спасибо!

Фев 02 2019 Обновление во второй половине дня

Ой, я забыл проверить эту ссылку в отношении транзакционной документации.

I 'Я не уверен, как использовать @Bean и @Transactional для одной и той же функции.

Можете ли вы показать мне пример?

Примеры @Bean, которые я видел, возвращают лямбду, которая затем загадочно вызывается позже.Нужно ли лямбда быть объявленным транзакционным?Это возможно?Если нет, нужно ли заменить лямбду потомком java.util.function.Consumer <>, функция принятия которого объявлена ​​с @Transactional?

Фев 05 2019 Обновление: решение найдено!

Я использовал новый лямбда-синтаксис Java8 и мне пришлось отказаться от него в пользу более старого синтаксиса внутреннего класса, чтобы я мог объявить функцию @Transactional.

  @Transactional
  class InitSpecialCommandLineRunner implements org.springframework.boot.CommandLineRunner{
      @Transactional // this is important!
      @Override
      public void run(String[] args) {
          int count = listProjectsForEachUser(); // this works!
      }
  }


  @org.springframework.context.annotation.Profile("initialize")
  @org.springframework.context.annotation.Bean
  @Transactional
  public org.springframework.boot.CommandLineRunner initSpecial() {
       return new InitSpecialCommandLineRunner(); // this works

  // How to declare this transactional?
  //  return args ->
  //  {
  //      int count = fetchUsers();
  //      Iterable<User> users;
  //  };

}

Надеюсь, это когда-нибудь поможет кому-то еще.

1 Ответ

0 голосов
/ 01 февраля 2019

Похоже, что транзакции охватывают только непосредственный вызов хранилища.

Чтобы исправить это, добавьте аннотацию @Transactional к методу, который должен определять область вашей транзакции.По крайней мере, метод, который содержит код, который вы нам показали.

Этот метод должен быть общедоступным и работать с компонентом Spring.Подробнее см. https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html.

...