当前位置: 首页 > 面试题库 >

Hibernate多对多-渴望获取方法与延迟

吴弘壮
2023-03-14
问题内容

hibernate的新手。

我有用户组多对多关系。三个表:User,Group和UserGroup映射表。

实体:

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

@Id
@Column (name = "username")
private String userName;

@Column (name = "password", nullable = false)
private String password;


@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
@JoinTable(name="usergroup", 
            joinColumns={@JoinColumn(name="username")}, 
            inverseJoinColumns={@JoinColumn(name="groupname")})
private Set<Group> userGroups = new HashSet<Group>();

... setter and getters



@Entity
@Table(name = "group")
public class Group {

@Id
@Column(name = "groupname")
private String groupName;

@Column(name = "admin", nullable = false)
private String admin;

@ManyToMany(mappedBy = "userGroups", fetch = FetchType.EAGER)
private Set<User> users = new HashSet<User>();

... setter and getters

注意,在组实体中,我正在使用获取方法EAGER。现在,当我打电话给DAO时,请使用以下条件来检索系统中的所有组:

  Criteria criteria = session.createCriteria(Group.class);
  return criteria.list();

我从mappgin表(用户组)获取所有行,而不是获取组的实际数量…

例如,如果我在用户表中

 username password
 -----------------
 user1     user1
 user2     user2

在组表中

 groupname admin
 ---------------
 grp1      user1
 grp2      user2

在用户组表中

 username groupname
 ------------------
 user1     grp1
 user2     grp2
 user1     grp2
 user2     grp1

结果将是以下列表-{grp1,grp2,grp2,grp1}

代替{grp1,grp2}

如果我将组实体的获取方法更改为LAZY,我将获得正确的结果,但是hibernate将LazyException抛出到另一个地方…

请协助我使用哪种提取方法,为什么?

谢谢!


问题答案:

懒惰的人会告诉你要始终FetchType.EAGER凭直觉来使用。这些人通常不担心数据库性能,只关心使开发工作更轻松。我要说的是您应该利用它FetchType.LAZY来提高性能。由于数据库访问通常是大多数应用程序的性能瓶颈,因此一点点帮助。

如果确实需要获取组的用户列表,只要您getUsers()在事务会话中进行呼叫,就不会得到LazyLoadingException所有新Hibernate用户的麻烦。

以下代码将为您提供所有组,而无需填充这些组的用户列表

//Service Class
@Transactional
public List<Group> findAll(){
    return groupDao.findAll();
}

以下代码将为您提供DAO级别的所有组的用户:

//DAO class
@SuppressWarnings("unchecked")
public List<Group> findAllWithUsers(){
    Criteria criteria = getCurrentSession().createCriteria(Group.class);

    criteria.setFetchMode("users", FetchMode.SUBSELECT);
    //Other restrictions here as required.

    return criteria.list();
}

编辑1:感谢Adrian Shum的这段代码

有关不同类型的FetchMode的更多信息,请参见此处

如果您不想只为访问集合对象而编写其他DAO方法,只要您与Session用于获取父对象的对象相同,则可以使用该Hibernate.initialize()方法来强制初始化子集合宾语。我不建议您List<T>对父对象执行此操作。这将对数据库造成相当大的负担。

//Service Class
@Transactional
public Group findWithUsers(UUID groupId){
    Group group = groupDao.find(groupId);

    //Forces the initialization of the collection object returned by getUsers()
    Hibernate.initialize(group.getUsers());

    return group;
}

我没有遇到必须使用上述代码的情况,但是它应该相对有效。有关更多信息,Hibernate.initialize()请参见此处

我已经在服务层中完成了此操作,而不是在DAO中获取它们,因为那样的话,您只需要在服务中创建一个新方法,而不必再创建单独的DAO方法。重要的是您已将getUsers()调用包装在事务中,因此将创建一个会话,Hibernate可以使用该会话来运行其他查询。也可以在DAO中通过向您的集合编写联接条件来完成此操作,但是我从来不必自己做。

就是说,如果您发现调用第二个方法的次数比调用第一个方法的次数多,请考虑将获取类型更改为EAGER并让数据库为您完成工作。



 类似资料:
  • 我从mappgin表(usergroup)中获取所有行,而不是实际的组数... 例如,如果我在用户表中 在组表中

  • 问题内容: SQLAlchemy支持渴望加载关系,这基本上是一条语句。但是,如果模型具有两个或多个关系,则可能是非常庞大的联接。例如, 该查询的性能实在是太差了,因为中和会产生一个巨大的表。但是和在这里没有关系,因此它们不应该是。它应该是两个分开的查询。并且由于会话具有某种程度的缓存,因此我将查询更改为此。 这次的性能要好得多。但是,我不认为这样做是正确的。我不确定会话结束时标签缓存是否会过期。

  • 问题内容: 我有一个我认为应该很普遍的问题,但找不到答案。 我有2个对象:组和用户。我的课程如下所示: 现在,当我尝试从数据库中获取用户时,它带来了所有组,所有组都带来了所有用户,依此类推。最后,我遇到了stackoverflow异常。 如何解决此问题,并且仍然具有双向关联以及到达列表中对象的能力? 问题答案: 如果使用属性(无论如何都应使用)将双向关联的一侧设为关联的 拥有 侧,是否会遇到相同的

  • 场景中,我正在处理用户和方案应用程序。网页用于创建和更新用户。同样,可以创建和更新scheme页面。现在使用hibernate,我与user to scheme表有多对多关系。我已经创建了USER SCHEME和USER\u SCHEME表并保存了它们。 该方案用户数量巨大。现在我有一个条件,如果一个用户更新了他的详细信息,如果他有10个以上的证书,那么在schema网页中,他必须以star aw

  • 在使用Hibernate几年后,问这个问题有点尴尬... 我有一个master_table,它: null

  • 我现在被IFPH第7章的一个问题困住了。 练习7.1.2内容如下: “排序的一个定义是取 详细给出表达式排序[3,4,2,1]的渴望和懒惰求值减少序列,解释它们的区别。” 现在,我先从急切的求值缩减序列开始,我假设它是最内部的缩减。 对我来说,这产生了... 这是已排序的列表。 现在对于惰性评估,我能想到的唯一减少序列与渴望评估完全相同。当然,Haskell对惰性评估进行最左边的最外层评估:但是我