Pergunta

I'm developing a web application using Spring MVC/Security/JPA/Hibernate.

I have a User class which have OneToMany relation with UserRole.

@Entity
@Table(name = "user_accounts")
@SuppressWarnings("serial")
public class User extends SimpleBaseEntity<Long> implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "email", length = 100, nullable = false, unique = true)
    private String email;

    @Column(name = "first_name", length = 100,nullable = false)
    private String firstName;

    @Column(name = "last_name", length = 100, nullable = false)
    private String lastName;

    @Column(name = "password", length = 255)
    private String password;

    @OneToMany(fetch = FetchType.EAGER, cascade={CascadeType.ALL}, mappedBy="user")
    @NotFound(action=NotFoundAction.IGNORE)
    private List<UserRole> roles;

    @Enumerated(EnumType.STRING)
    @Column(name = "sign_in_provider", length = 20)
    private SocialMediaService signInProvider;

    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "user_image", length=16777216)
    private byte[] userImage;


    ... skip

}

And the UserRole class has ManyToOne relation with User.

@Entity
@Table(name = "user_roles")
@SuppressWarnings("serial")
public class UserRole implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false, unique = true)
    private Long id;

    @Column(name = "user_id", length = 100, nullable = true)
    private String userId;

    @Enumerated(EnumType.STRING)
    @Column(name = "role", length = 20, nullable = false)
    private Role role;

    @ManyToOne
    @JoinColumn(name="user_id", referencedColumnName="email", insertable=false, updatable=false, nullable=false)
    @NotFound(action=NotFoundAction.IGNORE)
    private User user;

    ... skip

}

The User Repository interface is very simple.

public interface UserRepository extends JpaRepository<User, Long> {

    public User findByEmail(String email);

}

When I load user information using repository using a code snippet below, it retrieves User and UserRole data finely.

User user = userRepository.findByEmail("some@email.com");  // OK both User and UserRole

Here is the log file.

Hibernate: 
    select
        user0_.id as id1_9_,
        user0_.creation_time as creation2_9_,
        user0_.modification_time as modifica3_9_,
        user0_.email as email4_9_,
        user0_.first_name as first_na5_9_,
        user0_.last_name as last_nam6_9_,
        user0_.password as password7_9_,
        user0_.sign_in_provider as sign_in_8_9_,
        user0_.user_image as user_ima9_9_ 
    from
        user_accounts user0_ 
    where
        user0_.email=?
Hibernate: 
    select
        roles0_.user_id as user_id3_9_1_,
        roles0_.id as id1_10_1_,
        roles0_.id as id1_10_0_,
        roles0_.role as role2_10_0_,
        roles0_.user_id as user_id3_10_0_ 
    from
        user_roles roles0_ 
    where
        roles0_.user_id=?
Hibernate: 
    select
        user0_.id as id1_9_1_,
        user0_.creation_time as creation2_9_1_,
        user0_.modification_time as modifica3_9_1_,
        user0_.email as email4_9_1_,
        user0_.first_name as first_na5_9_1_,
        user0_.last_name as last_nam6_9_1_,
        user0_.password as password7_9_1_,
        user0_.sign_in_provider as sign_in_8_9_1_,
        user0_.user_image as user_ima9_9_1_,
        roles1_.user_id as user_id3_9_3_,
        roles1_.id as id1_10_3_,
        roles1_.id as id1_10_0_,
        roles1_.role as role2_10_0_,
        roles1_.user_id as user_id3_10_0_ 
    from
        user_accounts user0_ 
    left outer join
        user_roles roles1_ 
            on user0_.email=roles1_.user_id 
    where
        user0_.email=?

However, here is the problem.

If I update User information in a service class using save(merge) method of the UserRepository, the same findByEmail method DOES NOT retrieve UserRole(roles) information but only User information.

User oldUser = userRepository.findByEmail("some@email.com");  // OK both User and UserRole(roles)

// ... some modifications of "oldUser"

userService.updateUser(oldUser);  // This is Transactional and the table record is updated OK.

User newUser = userRepository.findByEmail("some@email.com");  // UserRole(roles) data is null

The hibernate log file is below.

# findByEmail oldUser
Hibernate: 
    select
        user0_.id as id1_9_,
        user0_.creation_time as creation2_9_,
        user0_.modification_time as modifica3_9_,
        user0_.email as email4_9_,
        user0_.first_name as first_na5_9_,
        user0_.last_name as last_nam6_9_,
        user0_.password as password7_9_,
        user0_.sign_in_provider as sign_in_8_9_,
        user0_.user_image as user_ima9_9_ 
    from
        user_accounts user0_ 
    where
        user0_.email=?
Hibernate: 
    select
        roles0_.user_id as user_id3_9_1_,
        roles0_.id as id1_10_1_,
        roles0_.id as id1_10_0_,
        roles0_.role as role2_10_0_,
        roles0_.user_id as user_id3_10_0_ 
    from
        user_roles roles0_ 
    where
        roles0_.user_id=?
Hibernate: 
    select
        user0_.id as id1_9_1_,
        user0_.creation_time as creation2_9_1_,
        user0_.modification_time as modifica3_9_1_,
        user0_.email as email4_9_1_,
        user0_.first_name as first_na5_9_1_,
        user0_.last_name as last_nam6_9_1_,
        user0_.password as password7_9_1_,
        user0_.sign_in_provider as sign_in_8_9_1_,
        user0_.user_image as user_ima9_9_1_,
        roles1_.user_id as user_id3_9_3_,
        roles1_.id as id1_10_3_,
        roles1_.id as id1_10_0_,
        roles1_.role as role2_10_0_,
        roles1_.user_id as user_id3_10_0_ 
    from
        user_accounts user0_ 
    left outer join
        user_roles roles1_ 
            on user0_.email=roles1_.user_id 
    where
        user0_.email=?

    # Update User
    update
        user_accounts 
    set
        modification_time=?,
        email=?,
        first_name=?,
        last_name=?,
        password=?,
        sign_in_provider=?,
        user_image=? 
    where
        id=?

# findByEmail newUser
Hibernate: 
    select
        user0_.id as id1_9_,
        user0_.creation_time as creation2_9_,
        user0_.modification_time as modifica3_9_,
        user0_.email as email4_9_,
        user0_.first_name as first_na5_9_,
        user0_.last_name as last_nam6_9_,
        user0_.password as password7_9_,
        user0_.sign_in_provider as sign_in_8_9_,
        user0_.user_image as user_ima9_9_ 
    from
        user_accounts user0_ 
    where
        user0_.email=?

Is there anyone can help me?

Thanks in advance.

Foi útil?

Solução

Finally, I found the reason of missing relation list data.

It was my mistake of transaction setting.

The "updateUser(oldUser)" method was not transactional.

After I changed it to transactional, everything work fine.

User oldUser = userRepository.findByEmail("some@email.com");  // OK both User and UserRole(roles)

// ... some modifications of "oldUser"

userService.updateUser(oldUser);  // This was not Transactional and it was the reason of the problem.

User newUser = userRepository.findByEmail("some@email.com");  // UserRole(roles) data is null
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top