Spring Data JPA- Hibernate多对多关系在链接实体表中插入null [英] Spring data JPA- Hibernate Many to Many relation is inserting null in link entity table

查看:60
本文介绍了Spring Data JPA- Hibernate多对多关系在链接实体表中插入null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我与用户之间有很多关系

I have many to many relation between user to role

用户实体:

import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Entity
@Data
@EqualsAndHashCode(callSuper = false, exclude = {"roles"})
@ToString( exclude = {"roles"})
@NoArgsConstructor
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    private String lanId;
    
    @OneToMany(mappedBy = "user",  cascade = CascadeType.ALL)
    private Set<UserRole> roles = new HashSet<>();

    
    public User(String lanId) {
    
        this.lanId = lanId;
    }
    
    
    // Utility Method to sync on both sides
    public void addRole(Role role, boolean isPrivileged) {
        
        UserRole userRole = new UserRole();
        userRole.setUser(this);
        userRole.setRole(role);
        userRole.setPrivileged(isPrivileged);
        roles.add(userRole);
        role.getUsers().add(userRole);
        
    }   
}

角色实体:

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Entity
@Data
@EqualsAndHashCode(callSuper = false, exclude = {"users"})
@ToString( exclude = {"users"})
@NoArgsConstructor
public class Role {
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    private String roleName;

    @OneToMany(mappedBy = "role" ,cascade =  CascadeType.ALL)
    private Set<UserRole> users = new HashSet<>();
    
    public  Role(String roleName) {
        this.roleName =roleName;
        
    }
}

用户角色实体:

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@Entity
@Data
@EqualsAndHashCode(callSuper = false ,exclude = {"privileged"})
@NoArgsConstructor
public class UserRole implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    
    @Id
    @ManyToOne
    private User user;
    
    @Id
    @ManyToOne
    private Role role;
    
    private boolean privileged;

}

服务等级:

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sample.m2m.dto.RolesDto;
import com.sample.m2m.repository.Role;
import com.sample.m2m.repository.RoleRepository;
import com.sample.m2m.repository.User;
import com.sample.m2m.repository.UserRepository;

@Service
public class SampleService {
    
    @Autowired
    private UserRepository userRepo;
    
    @Autowired
    private RoleRepository roleRepo;
    
    
    
    public void addEntity(String lanId,List<RolesDto> roles) {
        // adding roles to DB first
        addNewRoles(lanId,roles);
        addUserRole(lanId,roles);
    }
    
    @Transactional
    public void addNewRoles(String lanId,List<RolesDto> roles) {
        //Set<String> roles = Set.of("admin", "read","write");
    //  Set<String> roles = Set.of("opr");
        Set<Role> roleSet = new HashSet<Role>();
        
        for(RolesDto role :roles)
        {
            Role roleDB = roleRepo.findByRoleName(role.getRoleName());
            
            if(roleDB ==null) {
                roleDB = new Role(role.getRoleName());
                roleSet.add(roleDB);
            }
            
            
        }
        
        roleRepo.saveAll(roleSet);
        
    }
    
    
    
    @Transactional
    public void addUserRole(String lanId,List<RolesDto> roles) {
        
        
        //Set<String> roles = Set.of("admin", "read","write");
        //Set<String> roles = Set.of("opr");
        User userDB  = userRepo.findByLanId(lanId);
        
        if(userDB == null) {
            userDB = new User(lanId);
            
            
            for(RolesDto role : roles) {
                Role roledb = roleRepo.findByRoleName(role.getRoleName());
                userDB.addRole(roledb, true);
                    
            }
            
        }
        else
        {
            
            for(RolesDto role : roles) {
                Role roledb = roleRepo.findByRoleName(role.getRoleName());
                userDB.addRole(roledb, true);
                    
            }
            
        }
        
        userRepo.save(userDB);
        
    }

}

样品输入:1:首次保存-成功

SAMPLE INPUT: 1 : Saving for first time - SUCCESS

{
    "lanId":"ABC123",
    "roles" :[{
        "roleName" :  "opr"  
    }
    ]
}

样本输入2:将其他角色保存到同一用户-失败

SAMPLE INPUT 2 : Saving additional roles to the same user - FAILURE

{
    "lanId":"AB123",
    "roles" :[{
        "roleName" : "admin"
    },{
        "roleName" : "read"
    },
 {
        "roleName" : "write"
    }

    ]
}

异常:(试图将null插入用户和链接实体中的角色)

Exception: (Trying to insert null into user and role in link entity)

2020-09-18 11:12:34.379 DEBUG 24862 --- [nio-8080-exec-5] org.hibernate.SQL                        : 
    select
        userrole0_.user_id as user_id2_2_0_,
        userrole0_.role_id as role_id3_2_0_,
        userrole0_.privileged as privileg1_2_0_ 
    from
        pam.user_role userrole0_ 
    where
        userrole0_.user_id=? 
        and userrole0_.role_id=?
2020-09-18 11:12:34.379 TRACE 24862 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [1739260]
2020-09-18 11:12:34.379 TRACE 24862 --- [nio-8080-exec-5] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [BIGINT] - [1739261]
2020-09-18 11:12:34.393 ERROR 24862 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session : [com.sample.m2m.repository.UserRole#UserRole(user=null, role=null, privileged=true)]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.sample.m2m.repository.UserRole#UserRole(user=null, role=null, privileged=true)]] with root cause

javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.sample.m2m.repository.UserRole#UserRole(user=null, role=null, privileged=true)]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:123) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]

我在映射或用户实体的Utility方法中缺少某些内容吗?非常感谢您的帮助.

Am I missing something in the mapping or in the utility method of user entity . Any help is much appreciated.

推荐答案

UserRole属性不是表的主要ID,因此@Id不应位于表2上.

UserRole attributes aren’t the table’s primary ID so @Id should not be on these 2.

您应该向UserRole添加一个ID属性,并使用@Id和@GeneratedValue对其进行注释.

You should add an ID attribute to UserRole and annotate that with @Id and @GeneratedValue.

@ManyToOne将在数据库中产生外键

The @ManyToOne will result in a foreign key in the database

这篇关于Spring Data JPA- Hibernate多对多关系在链接实体表中插入null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆