如果将访存模式设置为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
答案 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();