2014-10-10 117 views
3

我有一些问题。Jpa多对多如何将数据插入到两个表中

我有3个表:

users (id, name, ..) 
roles (id, name) 
user-role (user_id, role_id) 

当我做很多一对多的关系,确实省了()我有3个刀片。

用户:

@Entity 
@Table(name = "user") 
public class User implements Serializable { 

    public static final String UK_EMAIL = "uk_email"; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id") 
    private Long id; 

    @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE}) 
    @JoinTable(
     name = "system_user_role", 
     joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, 
     inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = id")} 
    ) 
    private List<SystemRole> userRole; 

    public List<SystemRole> getUserRole() { 
     return userRole; 
    } 

SystemRole;

@Entity 
@Table(name = "system_role") 
public class SystemRole implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "id") 
    private Long id; 

    @Column 
    private String name; 

    @ManyToMany(fetch = FetchType.LAZY) 
    @JoinTable(
     name = "system_user_role", 
     joinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}, 
     inverseJoinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")} 
    ) 
    private List<User> users; 

    public List<User> getUsers() { 
     return users; 
    } 

    public void setUsers(List<User> users) { 
     this.users = users; 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

请告诉我,我可以将数据插入到两个表只,只进(用户和USER_ROLE? 我的角色名单,我不必添加一个新的角色,当我创建一个新的用户。

所以,当我这样做:

SystemRole role1 = systemRoleService.findOne("ROLE_ADMIN"); 
userForm.setUserRole(Lists.newArrayList(role1)); 
.... 
final User saved = userRepository.save(user); 
.... 

我得到一个错误:

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist:... 

如果我这样做:

@Service("userService") 
@Transactional 
public class UserServiceImpl implements UserDetailsService, ResourceService<User> { 
private final static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); 

@Autowired 
private UserDAO userRepository; 
@Autowired 
private SystemRoleDAO systemRoleRepository; 

@Override 
@Transactional(rollbackFor = ResourceException.class) 
public User create(User user) throws ResourceException { 
    try { 
     SystemRole role1 = systemRoleRepository.findOne(6l); 
     user.setUserRole(Lists.newArrayList(role1)); 

     user.setId(62l); // !!! if set user ID - it works CORRECT 

     final User saved = userRepository.save(user); 
     return saved; 
    } catch (DataIntegrityViolationException ex) { 
... 

的UserDAO:

@Repository 
public interface UserDAO extends JpaRepository<User, Long> { 
... 

SystemRoleDAO:

@Repository 
public interface SystemRoleDAO extends JpaRepository<SystemRole, Long> { 

它的工作原理,但我有3个刀片。

当我创建一个新用户时,我需要从列表中选择一个角色,将其添加到用户并保存新用户。

非常感谢。

+0

请明确 – 2014-10-10 08:54:21

+0

你如何分配的角色?看起来您正在创建新角色,而不是使用现有角色。并且请避免使用像List这样的rawtypes。改用'列表'代替。 – Tom 2014-10-10 08:54:27

+0

我猜想有一个插入,因为角色,因为你创建一个新的角色,而不是分配一个现有的,但你需要发布的代码创建和保存。 – 2014-10-10 08:54:38

回答

0

我猜你的代码userRepository.save内()方法正在调用

entityManager.persist(user); 

相反,你应该叫

entityManager.merge(user); 

通过这样做,而不是插入一个新的角色时,Hibernate将检查具有相同ID的角色是否已经存在,并且如果是这种情况,则将该角色附加到用户实体(前提是级联类型包括合并操作)。

你需要调用合并的原因是你正在使用已经加载的角色实体(通过systemRoleService.findOne(“ROLE_ADMIN”)),然后从持久化上下文中分离出来,所以当你尝试时这个实体是分离的保存用户。如果Role没有被分离,你可以在User实体上调用persist()而不是merge()。

+0

嗨,谢谢,但我使用'org.springframework.data.jpa.repository.JpaRepository'接口并调用方法'save()'从它中查看。 – user1647166 2014-10-10 09:48:06

+0

请看这个http:// stackoverflow.com/questions/15943783/how-to-save-a-new-entity-that-refers-existing-entity-in-spring-jpa – Giovanni 2014-10-10 10:14:18

+0

我改变了我的代码,但是...... :(请带一个看变化谢谢 – user1647166 2014-10-10 12:25:12

1

@Entity @Table(name = “用户”)

公共类用户实现Serializable {

public static final String UK_EMAIL = "uk_email"; 

@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
@Column(name = "id") 
private Long id; 

@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE}) //Make CascadeType.Detached this should solver your problem 
@JoinTable(
    name = "system_user_role", 
    joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, 
    inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = id")} 
) 
private List<SystemRole> userRole; 

public List<SystemRole> getUserRole() { 
    return userRole; 
} 
相关问题