Hibernate @ Many-To-Many通过关联进行获取(stackoverflow)

时间:2018-07-29 14:24:33

标签: java hibernate many-to-many

如果将访存模式设置为EAGER,则会收到一个stackoverflow错误,如果未设置EAGER,则会引发另一个错误。如何安排双向关联以双向导航?

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

    public User(String name, Set<Role> roles) {
        this.name = name;
        this.roles = roles;
    }

    public User() {
    }
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    @ManyToMany
    @JoinTable(name = "test_join", joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles = new HashSet<>();

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 31 * hash + this.id;
        hash = 31 * hash + Objects.hashCode(this.name);
        hash = 31 * hash + Objects.hashCode(this.roles);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final User other = (User) obj;
        if (this.id != other.id) {
            return false;
        }
        if (!Objects.equals(this.name, other.name)) {
            return false;
        }
        if (!Objects.equals(this.roles, other.roles)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "User{" + "id=" + id + ", name=" + name + ", roles=" + roles + '}';
    }

}

@Entity
@Table(name = "test_roles")
public class Role implements Serializable {

    public Role(String name, Set<User> users) {
        this.name = name;
        this.users = users;
    }

    public Role() {
    }
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    private String name;
    @ManyToMany
    @JoinTable(name = "test_join", joinColumns = @JoinColumn(name = "role_id"),
            inverseJoinColumns = @JoinColumn(name = "user_id"))
    private Set<User> users = new HashSet<>();

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

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

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

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 83 * hash + this.id;
        hash = 83 * hash + Objects.hashCode(this.name);
        hash = 83 * hash + Objects.hashCode(this.users);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Role other = (Role) obj;
        if (this.id != other.id) {
            return false;
        }
        if (!Objects.equals(this.name, other.name)) {
            return false;
        }
        if (!Objects.equals(this.users, other.users)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Role{" + "id=" + id + ", name=" + name + ", users=" + users + '}';
    }

}

    @Repository(value = "userdao")
@Transactional
public class UserDaoImpl implements UserDao {

    public UserDaoImpl(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public UserDaoImpl() {
    }

    @Autowired
    private SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    private Session currentSession() {
        return sessionFactory.getCurrentSession();
    }

    @Override
    public void addUser(User user) {
        currentSession().save(user);
    }

    @Override
    @Transactional(readOnly = true)
    public List<User> getAllUsers() {
        return currentSession().createQuery("FROM User u").list();
    }

    @Override
    public void updateUser(User user) {
        currentSession().update(user);
    }

    @Override
    public void deleteUser(User user) {
        currentSession().delete(user);
    }

    @Override
    public User getUserByName(String name) {
        return (User) currentSession().createQuery("FROM User WHERE name = '" + name + "'").uniqueResult();
    }

    @Override
    public User getUserById(int id) {
        return (User) currentSession().createQuery("FROM User WHERE id = " + id).uniqueResult();
    }

}

public class Main {

    public static void main(String[] args) {

        UserDao userDao = (UserDao) SpringContext.getContext().getBean("userdao");

        List<User> users = userDao.getAllUsers();
        for (User user : users) {
            System.out.println(user);
        }

    }
}
  

信息:HHH000397:在线程中使用ASTQueryTranslatorFactory异常   “主要” org.hibernate.LazyInitializationException:懒惰地失败   初始化角色集合:com.entities.User.roles,无法   初始化代理-没有会话   org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)

     

WARN:HHH000100:故障安全清理(集合):   org.hibernate.engine.loading.internal.CollectionLoadContext@fd53053   线程“ main”中的异常java.lang.StackOverflowError位于   java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)     在java.util.concurrent.locks.ReentrantLock.unlock(Reentra

1 个答案:

答案 0 :(得分:0)

应该没困难。理解我认为您希望用户成为关系的拥有实体,因此,mappedBy =“ roles”,然后在用户中设置角色是您保持关系的方式。您可以用任何一种方法查询,但是您不想让它们更EAGER,否则您将获得不受限制的递归获取。

@Entity
public class User {
    @Id @GeneratedValue private int id;
    @ManyToMany private Set<Role> roles;

@Entity
public class Role {
    @Id @GeneratedValue private int id;
    @ManyToMany(mappedBy="roles") private Set<User> users;

tx.begin();
Role role1 = new Role();
em.persist(role1);
Role role2 = new Role();
em.persist(role2);
User user1 = new User();
Set<Role> user1Roles = new HashSet<>();
user1Roles.add(role1);
user1.setRoles(user1Roles);
em.persist(user1);

User user2 = new User();
Set<Role> user2Roles = new HashSet<>();
user2Roles.add(role1);
user2Roles.add(role2);
user2.setRoles(user2Roles);
em.persist(user2);
tx.commit();

em.clear();

List<User> users = em.createQuery("select distinct u from User u left join fetch u.roles", User.class).getResultList();

users.forEach( u-> System.out.println(u + ":" + u.getRoles()));

em.close();