草庐IT

java - hibernate 多对多-获取方法渴望与懒惰

coder 2024-03-05 原文

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()在交易 session 中,您不会得到 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 提供此代码

有关不同类型的更多信息 FetchModehere

如果您不想为了访问您的集合对象而编写不同的 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() 的更多信息见here

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

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

关于java - hibernate 多对多-获取方法渴望与懒惰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24150199/

有关java - hibernate 多对多-获取方法渴望与懒惰的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  5. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  8. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  9. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  10. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

随机推荐