Jpa多对多如何才能将数据插入到2个表中

时间:2014-10-10 08:50:29

标签: java hibernate jpa spring-data-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;
    }
}

请告诉我,我可以只将数据插入2个表中,只能插入(User和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个插页。

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

非常感谢。

2 个答案:

答案 0 :(得分:1)

@Entity @Table(name =&#34; user&#34;)

public class User实现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;
}

答案 1 :(得分:0)

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

entityManager.persist(user);

相反,你应该打电话

entityManager.merge(user);

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

您需要调用merge的原因是您正在使用已加载的Role实体(通过systemRoleService.findOne(“ROLE_ADMIN”))然后从持久性上下文中分离,因此当您尝试将此实体分离时保存用户。如果未分离Role,则可以在User实体上调用persist()而不是merge()。