Почему Hibernate удаляет мои записи коллекции, когда все, что я делаю, это список?

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

моя настройка-стандартное приложение 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 entity manager.

<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>

я упускаю что-то очевидное здесь?

1 ответов


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

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

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

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

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

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

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

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

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