Hibernate retrieve null for OneToMany collection

Viewed 9481

My problem is that hibernate retrieve null in the value of the @OneToMany Set organizationMemberCollection when fetching an instance on the following object :

UserAccount.java :

@Entity
@Table(name="USER_ACCOUNT")
public class UserAccount {

    @Id
    @Column(name = "id", nullable = false)
    @SequenceGenerator(name = "generator", sequenceName = "USER_ACCOUNT_id_seq", allocationSize=1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
    private Long id;

    @Column(name = "EMAIL", nullable = false)
    private String email;

    @Column(name = "PASSWORD_HASH")
    private String passwordHash;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "userAccount")
    private Set <OrganizationMember> organizationMemberCollection;

    ...

    /*
     * getters and setters
     */
}

Here is the Object that "owns" the association :

OrganizationMember.java :

@Entity
@Table(name="ORGANIZATION_MEMBER")
public class OrganizationMember{

    @Id
    @Column(name = "id", nullable = false)
    @SequenceGenerator(name = "generator", sequenceName = "ORGANIZATION_MEMBER_id_seq", allocationSize=1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "generator")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "USER_ACCOUNT_ID", nullable = false)
    private UserAccount userAccount;    

    ...

    /*
     * getters and setters
     */
}

In this application we have two different configuations :

  • Production, where Hibernate is connected to a PostgreSQL database. Here is the sessionFactory configuration for prod :

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="hibernateProperties"> <props> <prop key="hibernate.jdbc.batch_size">10</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.cglib.use_reflection_optimizer">false</prop> </props> </property> ... </bean>

  • Test, where Hibernate is conencted to an in memory HSQLDB database :

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.cglib.use_reflection_optimizer">false</prop> <prop key="hibernate.hbm2ddl.auto">create-drop</prop> <prop key="hibernate.cache.use_second_level_cache">false</prop> <prop key="hibernate.cache.use_query_cache">false</prop> </props> </property> ... </bean>

This issue only show up in testing configuration; In production configuration everything's going nicely and I can get the collection. However, when I fetch an UserAccount in the test configuration I get null in the organizationMemberCollection property (Not an empty Set).

After some hours of research through google and Hibernate's doc I still haven't found any post relating to the same issue/behaviour, so I'm a lillte bit lost and help would be greatly appreciated !

I can of course provide more information if needed, Thanks !

Edit :

Test higlighting the problem :

@Test
@Transactional
public void testFindUserAccount_OrganizationMemberCollectionFetching() {

    assertNotNull(userAccountDao.findUserAccount("user1@test.fr"));  //NoProblem
    assertNotNull(userAccountDao.findUserAccount("user1@test.fr").getCabinetMemberCollection());  //Fails

}

With the following findUserAccount dao

public UserAccount findUserAccount(String email) {
    if (email == null) {
        return null;
    }
    UserAccount userAccount = (UserAccount) this.sessionFactory
            .getCurrentSession().createCriteria(UserAccount.class)
            .add(Restrictions.eq("email", email).ignoreCase())
            .uniqueResult();
    if (userAccount == null) {
        throw new ObjectNotFoundException("UserAccount.notFound");
    } else {
        return userAccount;
    }
}
3 Answers

In my case it was because I had "transient" as the entity was not serializable an Sonar told me to add the transient keyword

@OneToMany(mappedBy = "message", cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
    private transient List<UserReadSystemMessage> usersRead;

Note the transient

Related