2013-03-05 5 views
6

У меня, кажется, довольно странная проблема. Я показываю пользователей и их роли в JSP. По некоторым причинам роли отображаются только при первой загрузке страницы. Я обновляю страницу и все роли удаляются из базы данных!Почему Hibernate удаляет мои записи коллекции, когда все, что я делаю, это список?

Моя настройка - это стандартное приложение Spring MVC, JPA + Hibernate (по весне). (Spring 3.2.x, Hibernate 4.1.8)

У меня есть две сущности - User и Role, как показано ниже (подразумевается, сеттеров и добытчиками)

@Entity 
public class User { 
    @Id 
    @GeneratedValue 
    private int id; 

    private String name; 

    @ManyToMany 
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) 
    private Set<Role> roles = new HashSet<>(); 
} 

@Entity 
public class Role { 
    @Id 
    private String id; 

    private String name; 
} 

У меня есть хранилище данных Spring, который не делает определите любые дополнительные методы.

public interface UserRepository extends CrudRepository<User, Integer> { 
} 

У меня есть служба и контроллер, соответствующие методы которой следующие.

// service 
@Transactional(readOnly = true) 
public Iterable<User> findAll() { 
    return userRepository.findAll(); 
} 

// controller 
@RequestMapping 
public String showUsers(ModelMap model) { 
    model.put("users", userService.findAll()); 

    return "admin/users"; 
} 

В моем JSP я пытаюсь отобразить всех пользователей и любые связанные роли.

<c:forEach var="user" items="${users}"> 
    <tr> 
     <td>${user.name}</td> 
     <td> 
      <c:forEach var="role" items="${user.roles}"> 
       ${role.name} 
      </c:forEach> 
     </td> 
    </tr> 
</c:forEach> 

Как я уже говорил ранее, записи в моем user_role таблицы удаляются после того, как эта страница была оказана.

При включении DEBUG для org.hibernate и позволяет протоколирование запросов, вот что я нашел в журналах:

22:36:25 DEBUG Collection dereferenced: [com.adarshr.domain.User.roles#1] [Collections.java:76] 
22:36:25 DEBUG Flushed: 0 insertions, 0 updates, 0 deletions to 2 objects [AbstractFlushingEventListener.java:117] 
22:36:25 DEBUG Flushed: 0 (re)creations, 0 updates, 1 removals to 1 collections [AbstractFlushingEventListener.java:124] 
22:36:25 DEBUG Deleting collection: [com.adarshr.domain.User.roles#1] [AbstractCollectionPersister.java:1124] 
22:36:25 DEBUG 
    delete 
    from 
     user_role 
    where 
     user_id=? [SqlStatementLogger.java:104] 
22:36:25 DEBUG Done deleting collection [AbstractCollectionPersister.java:1182] 

Совершенно очевидно, что-то подозрительное происходит здесь. Почему моя коллекция разыгрывается в первую очередь?

Это мое определение фабричного менеджера JPA.

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="mainDataSource" /> 
    <property name="packagesToScan" value="com.adarshr.domain" /> 
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
    </property> 
    <property name="jpaProperties"> 
     <value> 
      hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect 
      hibernate.format_sql=${hibernate.format.sql} 
      hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy 
      hibernate.show_sql=${hibernate.show.sql} 
      hibernate.enable_lazy_load_no_trans=true 
     </value> 
    </property> 
</bean> 

Я пропустил что-то очевидное здесь?

+0

Откуда у вас «enable_lazy_load_no_trans»? Все, что я могу найти, это люди, которые говорят, что это багги и не рекомендуются для использования. –

+0

От http://stackoverflow.com/questions/578433/how-to-solve-lazy-initialization-exception-using-jpa-and-hibernate-as-provider – adarshr

+0

«Следует использовать с осторожностью, это преуменьшение!» «Это действительно просто целевая функция ...» «... это очень плохая идея в общем использовании». «использовать на свой страх и риск». «... это не та функция, которую мы действительно считаем, люди должны использовать, не зная возможных последствий». https://hibernate.onjira.com/browse/HHH-7457 Хм, вы чувствуете тему там? Не используйте его. –

ответ

5

Поскольку код, который вы отправили, кажется правильным, я угадываю здесь.

Первое, что я хотел бы предложить, это удалить эту инициализацию (это единственное место, где удаляются роли), которая в то же время является хорошей идеей в целом (см. Комментарии ниже). Я думаю, может помешать hibernate.enable_lazy_load_no_trans=true, который был известно, что leak connections в прошлом:

private Set<Role> roles = new HashSet<>(); 

Вторая попытка будет проверить, и какие изменения, если вы также аннотировать обратную сторону вашего ManyToMany отношения с mappedBy.

Третья попытка состояла бы в том, чтобы с нетерпением загрузить сборку исправляет проблему (усугубляет положение enable_lazy_load_no_trans еще больше), используя FetchType, Hibernate.initialize() из того, что вы хотите.

Последний один избавляется от enable_lazy_load_no_trans и использовать OpenSessionInView

EDIT: ааа, последний, возможно * есть он это ошибка (спящий режим 4.1.8 и 4.1.9 пострадавших): https://hibernate.onjira.com/browse/HHH-7971

Итак, сделав снимок с 4.1.7 может дать лучшие результаты (или, может быть, еще хуже).

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

+0

Плохая идея. * Всегда * инициализировать типы коллекций в пустой коллекции. Я гарантирую, что это не основная причина. –

+0

@ Ryan Stewart Я согласен, моя идея, которая может быть проблемой с hibernate.enable_lazy_load_no_trans = true, и я делал снимок. –

+0

Просто увидел отчет об ошибке. У меня точно такая же проблема. Я попробую отправить тестовый пример. Понижение уровня 4.1.7, похоже, поставило проблему. Однако отсутствие инициализации коллекции не повлияло. Даже с OEMIVFilter работал. – adarshr