我在持久层中存在多对多关联的问题。我的情况如下:
一个用户可以具有多个角色,并且一个角色可以具有与其连接的多个用户。在测试期间,我遇到了一个奇怪的行为。我创建了角色对象和几个用户对象。该角色已设置给每个用户。此后,使用DAO保存了用户。然后,加载一个用户,以检查他是否在保存用户对象之前获得了传递给他的角色。呼叫getRoles()
用户表明角色设置正确。
要检查反方向是否也起作用,可以使用角色DAO从数据库中加载角色对象。但是,调用getUsers()
角色对象只会返回一个空集,尽管它应包含具有该角色的所有用户。
我仔细检查了数据库表,但是一切似乎都没问题。用户,角色和user_role表均已正确填写。
那么,为什么角色对象不包含任何用户?
我在以下类中使用Hibernate和Spring。
用户类别
@Entity
@Table
public class User extends BusinessObject {
...
// Option 1
@ManyToMany(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
targetEntity=Role.class)
@JoinTable(name= "user_role",
joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name="role_id")})
// Option 2
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name= "user_role",
joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name="role_id")})
private Set<Role> roles = new HashSet<Role>();
...
}
角色类
@Entity
@Table
public class Role extends BusinessObject {
...
// Option 1
@ManyToMany(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy= "roles",
targetEntity = User.class)
// Option 2
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name= "user_role",
joinColumns = {@JoinColumn(name="role_id")},
inverseJoinColumns = {@JoinColumn(name="user_id")})
private Set<User> users = new HashSet<User>();
...
}
为了测试,我在JUnit测试类中使用以下代码。
@Test
public void test(){
Transaction trans = sessionFactory.getCurrentSession().beginTransaction();
Role userAdminRole = new Role();
userAdminRole.setName(RoleName.USER_ADMIN);
Role userRole = new Role();
userRole.setName(RoleName.USER);
User user1 = new User();
user1.setEmail("user1@user.de");
user1.getRoles().add(userAdminRole);
user1.getRoles().add(userRole);
userDao.save(user1);
User user2 = new User();
user2.setEmail("user2@user.de");
user2.getRoles().add(role);
userDao.save(user2);
User user3 = new User();
user3.setEmail("user3@user.de");
user3.getRoles().add(role);
userDao.save(user3);
trans.commit();
User loadedUser = userDao.load(user1.getId());
// Tests passes
Assert.assertNotNull(loadedUser);
Assert.assertEquals(user1, loadedUser);
Set<Role> roles = loadedUser.getRoles();
// Tests passes
Assert.assertEquals(2, roles.size());
Role loadedUserAdminRole = roleDao.findByName(RoleName.USER_ADMIN);
Set<User> users = loadedUserAdminRole.getUsers();
// Test fails: Count is 0 instead of 3 !!!!!!!
Assert.assertEquals(3, users.size());
}
更新
对不起,我忘了提到一件事。当我测试代码时,我当然没有在每个类文件中两次标记多对多关联。相反,我在每个类文件中使用了选项1或选项2。
问题可能是由于您两次映射了相同的双向关联。如果您对相同的联接表或联接列两次告诉Hibernate,则存在问题。在双向关联中,关联的一端必须映射该关联,而另一端必须使用mappedBy
属性告诉Hibernate这是另一端的逆。
由于多对多是完全对称的,因此请选择一端作为所有者(即,映射关联并因此具有@JoinTable
注释的一端)。另一侧只是反面,因此没有@JoinTable
注释,但具有mappedBy
属性。
例:
@Entity
@Table
public class User extends BusinessObject {
...
// This end is the owner of the association
@ManyToMany
@JoinTable(name= "user_role",
joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name="role_id")})
private Set<Role> roles = new HashSet<Role>();
...
}
@Entity
@Table
public class Role extends BusinessObject {
...
// This end is not the owner. It's the inverse of the User.roles association
@ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<User>();
...
}
补充笔记:
Set
。如果Set是一个Set<SomeInterface>
mappedBy
属性的端)考虑在内以保持关联。假设我有这些类,请注意实体无论如何都不相关。 假定我有一个类,它的属性为,我可以在其中存储一个笔记本ID列表或任何字符串ID。假设有idsPointingToanEntity=[1,2,3],那么这个[1,2,3]在数据库中有一个等效的膝上型计算机条目。 注意:也可以是另一个实体,使不是一个选项
问题内容: 我想更好地了解之间的区别 (1)传统的 多值关系/关联 和 (2) 可嵌入(和基本)类型 的JPA2 集合 我看到了语法上的差异,但想知道是否还会 影响性能 。在后台,数据库实现看起来非常相似。 凭直觉,我通常会使用for 组成方案 。但是即使那样感觉也很相似。 我在这里错过了本质吗?在某些方面,一个比另一个更有效吗? 谢谢你J 问题答案: 凭直觉,我通常将@ElementCollec
我有两个类和,它们具有一对多关系。 假设我已经在我的数据库结构中持久化了,如下所示: ---编辑--- 实体不是什么花哨的东西,比如:
https://www.geeksforgeeks.org/count-of-larger-elements-on-right-side-of-each-element-in-an-array/#:~: text=朴素的做法:最简单的做法,一边然后打印出来。 我试图以大于左边数字的顺序计算数字,就像上面网站上描述的那样,但网站中的输出是arraylist,但我只想要一个数字,它是arraylist
问题内容: 我一直遇到这个问题: 我想让hibernate管理一个表示集合集合的表。例如: 地图地图 套装清单 清单地图 例如,我希望能够代表这一点: 作为一个表: 没有自定义的hibernate代码似乎是不可能的,我不介意。但是我希望有人对自定义代码的外观有所指导。 我应该扩展AbstractPersistentCollection吗? CompositeUserType? 可以管理多个表是否正