简体   繁体   中英

Hibernate OneToOne bidirectional functionality not working

User table not saving PasswordInfo object automatically Here are my entities

User entity

@Entity
@Table(name = "user")
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    
    @Column(name = "name")
    private String name;

    @Column(name = "username")
    private String userName;

    @Column(name = "password")
    private String password;
    
    @Column(name = "emp_id")
    private int empId;
    
    @Column(name = "designation")
    private String designation;
    
    @Column(name = "status")
    private String status;
    
    @Column(name = "email_id")
    private String emailId;
    
    @Column(name = "account_status")
    private String accountStatus;
    
    @Column(name = "validity_date")
    private Date validityDate;
    
    @Column(name = "deactivation_date")
    private Date deactivationDate;
    
    @Column(name = "deactivated_by")
    private String deactivatedBy;
    
    @Column(name = "deactivation_remarks")
    private String deactivationRemarks;
    
    @OneToMany(fetch = FetchType.LAZY,
            mappedBy = "user",
            cascade = {CascadeType.PERSIST,CascadeType.MERGE,
                    CascadeType.DETACH,CascadeType.REFRESH})
    private List<LoginDetails> loginDetails;
    
    // add convenience methods for bi-directional relationship for LoginDetails
    public void add(LoginDetails tempLoginDetails) {
        if(loginDetails == null) {
            loginDetails = new ArrayList<LoginDetails>();
        }
        
        loginDetails.add(tempLoginDetails);
        
        tempLoginDetails.setUser(this);
    }
    
    @OneToOne(mappedBy = "user", fetch = FetchType.LAZY,
            cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
                        CascadeType.REFRESH})
    private PasswordInfo passwordInfo;
    
    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "users_roles", 
    joinColumns = @JoinColumn(name = "user_id"), 
    inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Collection<Role> roles;
    
    @ManyToOne(fetch = FetchType.LAZY,cascade= {CascadeType.PERSIST,CascadeType.MERGE,
            CascadeType.DETACH,CascadeType.REFRESH})
    @JoinColumn(name="department_id")
    private Department department;
    
    @ManyToOne(fetch = FetchType.LAZY,cascade= {CascadeType.PERSIST,CascadeType.MERGE,
            CascadeType.DETACH,CascadeType.REFRESH})
    @JoinColumn(name="branch_id")
    private Branch branch;
    
    /*  
     * TIMESTAMPS START
     * */
    
    @Temporal( TemporalType.TIMESTAMP )
    @CreationTimestamp
    @Column(name = "creation_date")
    private Date creationDate;
    
    @UpdateTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updation_date")
    private Date updationDate;
    
    @ManyToOne(fetch = FetchType.LAZY,cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
            CascadeType.REFRESH})
    @JoinColumn(name="created_by")
    private User createdBy;

    @OneToMany(mappedBy="createdBy")
    private Set<User> createdBySet = new HashSet<User>();
    
    @ManyToOne(fetch = FetchType.LAZY,cascade={CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
            CascadeType.REFRESH})
    @JoinColumn(name="updated_by")
    private User updatedBy;

    @OneToMany(mappedBy="updatedBy")
    private Set<User> updatedBySet = new HashSet<User>();
    
    @PrePersist
    protected void onCreate() {
        creationDate = new Date();
    }

    @PreUpdate
    protected void onUpdate() {
        updationDate = new Date();
    }
    
    /*  
     * TIMESTAMPS END
     * */
    
    public User() {

    }

//  getter and setters and imports are written in real code, i have omitted them here
    
    
}

PasswordInfo entity

@Entity
@Table(name = "password_info")
public class PasswordInfo {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    
    @Column(name = "last_password_1")
    private String lastPassword1;
    
    @Column(name = "last_password_2")
    private String lastPassword2;
    
    @Column(name = "last_password_3")
    private String lastPassword3;
    
    @Column(name = "last_password_4")
    private String lastPassword4;
    
    @Column(name = "last_password_5")
    private String lastPassword5;
    
    @Column(name = "forced_password_flag")
    private String forcedPasswordFlag;
    
    @Column(name = "pass_count")
    private int passCount;
    
    @Column(name = "password_date")
    private Date passwordDate;
    
    @OneToOne(fetch = FetchType.LAZY,cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
            CascadeType.REFRESH})
    @JoinColumn(name="user_id")
    private User user;
    
    @Temporal( TemporalType.TIMESTAMP )
    @CreationTimestamp
    @Column(name = "creation_date")
    private Date creationDate;
    
    @PrePersist
    protected void onCreate() {
        creationDate = new Date();
    }
    
    public PasswordInfo() {

    }

    //  getter and setters and imports are written in real code, i have omitted them here
}

This is my save method in service class

@Override
    @Transactional
    public String save(ReportUser reportUser) {
        User user = new User();
         // assign user details to the user object
        user.setUserName(reportUser.getUserName());
        user.setPassword(passwordEncoder.encode(reportUser.getPassword()));
        user.setName(reportUser.getName());
        user.setEmpId(reportUser.getEmpId());
        user.setDesignation(reportUser.getDesignation());
        user.setEmailId(reportUser.getEmailId());
        user.setStatus(reportUser.getStatus());
        user.setEmailId(reportUser.getEmailId());
        user.setAccountStatus(reportUser.getAccountStatus());
        user.setValidityDate(reportUser.getValidityDate());
        
        String loggedInUser = jwtUtil.getUsername();
        
        logger.info(">>>>> Logged In USER " + loggedInUser);
        
        Department theDepartment = departmentDao.getDepartment(reportUser.getDepartmentId());
        
        Branch theBranch = branchDao.getBranch(reportUser.getBranchId());
        
        User createdByUser = userDao.findByUserName(loggedInUser);
        
        user.setBranch(theBranch);
        user.setDepartment(theDepartment);
        user.setCreatedBy(createdByUser);
        
        
        String[] roleArr = reportUser.getFormRole().split(",");
        
        List<Role> roleList = new ArrayList<Role>();
        
        for(String r: roleArr) {
            roleList.add(roleDao.findRoleByName(r));
        }
                        
        Collection<Role> roles = roleList;
        
        user.setRoles(roles);
        
        ParameterMst pmst = otherDao.getParameterValueById(1L);
        
        int passwordExpirationDays = Integer.valueOf(pmst.getValue());
        
        PasswordInfo pInfo = new PasswordInfo();
        
        // Add passwordExpirationDays to current date
        Date passwordExpirationDate =  DateUtils.asDate(LocalDate.now().plusDays(passwordExpirationDays));
        
        logger.info(">>>>> Password Expiration Date " + passwordExpirationDate);
        
        pInfo.setPasswordDate(passwordExpirationDate);
        pInfo.setPassCount(12);
        pInfo.setUser(user);
        
        user.setPasswordInfo(pInfo);
        
        
        
         // save user in the database
        userDao.save(user);
    
        
        return user.getUserName();
    }

This is save in DAO Implementation

@Override
    public void save(User user) {
        // get current hibernate session
        Session currentSession = sessionFactory.getCurrentSession();

        currentSession.saveOrUpdate(user);

    }

Due to bi-directional relationship set in User, i should be able to update both in one go, rather than doing separately. Why this isn't working?

Please Help!

Don't use mappedBy and @JoinColumn together as they serve slightly different purposes.

See the uses of both and use either one of them.

Try removing @JoinColumn annotation from PasswordInfo entity.

Try to annotate like this

In class PasswordInfo:

@OneToOne(mappedBy = "passwordInfo")
private User user;

In class User

@OneToOne()
private PasswordInfo passwordInfo;

mappedBy say that User table is the owner of the relationship using its propertie passwordInfo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM