使用 @OneToOne 和 @OneToMany 时如何使 Hibernate OUTER JOIN

2024-03-15

假设我有一张名为employee与领域employee_id, name and supervisor_id and employee_supervisor与领域supervisor_id and name。存在外键关系employee and employee_supervisor表关于supervisor_id柱子。

如果我在Employee类,我如何确保 Hibernate 使用 LEFT OUTER JOIN 来连接关联实体?


在我的测试中,Hibernate 默认执行 LEFT OUTER JOIN。但是,您可以确保它将始终使用带注释的 LEFT OUTER JOIN。我花了一些时间使用双向一对多映射来模拟您的情况我的模板 https://stackoverflow.com/q/24257449/2357233作为基础,然后更改类名称以符合您的情况。

我想出的课程如下:

职工监事班:

@Entity(name="EMPLOYEE_SUPERVISOR")
public class EmployeeSupervisor {
    @Id
    @GenericGenerator(name = "gen", strategy = "increment")
    @GeneratedValue(generator = "gen")
    @Column(name = "id")
    private int supervisorId;

    @Column
    private String name;

    @OneToMany(mappedBy = "supervisor")
    private List<Employee> employees;
    ....
}

员工类别:

@Entity
public class Employee {
    @Id
    @GenericGenerator(name = "gen", strategy = "increment")
    @GeneratedValue(generator = "gen")
    @Column(name = "id")
    private int employeeId;

    @Column
    private String name;

    @ManyToOne
    @Fetch(FetchMode.JOIN)
    @JoinColumn(name = "supervisorId")
    private EmployeeSupervisor supervisor;
    ....
}

确保您始终使用的注释LEFT OUTER JOIN is the @Fetch(FetchMode.JOIN注解。这告诉 Hibernate 使用 a 加载同一个 select 语句中的关联记录LEFT OUTER JOIN (see 文档 http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch20.html#performance-fetching对于其他类型的FetchMode以及每个人的作用)。

然后我在 jUnit 中模拟了数据库,配置 Hibernate 以在 log4j 中打印所有生成的 SQL

log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.type=TRACE

并运行了一个非常基本的单元测试。

public class EmployeeDAOTest extends SpringTest{

    @Autowired
    private EmployeeDAO dao;

    private Employee testLinkedEmployee;
    private Employee testUnlinkedEmployee;
    private EmployeeSupervisor testSupervisor;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        System.out.println("Starting DAO Test");
    }

    @AfterClass
    public static void tearDownAfterClass() throws Exception {
        System.out.println("Finished DAO Test");
    }

    @Before
    public void setUp() throws Exception {
        //Irrelevant horrible setup code snipped.
        /* Set up 2 employees and a EmployeeSupervisor in the database.
         * Link one employee to the EmployeeSupervisor and not the other
         */
    }

    @Test
    @Transactional
    public void test() {
        Employee actualLinkedEmployee = dao.getEmployee(testLinkedEmployee.getEmployeeId());
        Employee actualUnlinkedEmployee = dao.getEmployee(testUnlinkedEmployee.getEmployeeId());

        assertNotNull("The linked employee's supervisor didn't get selected.", actualLinkedEmployee.getSupervisor());
        assertNull("The unlinked employee's supervisor was not null.", actualUnlinkedEmployee.getSupervisor());
    }
}

我的 DAO 非常初级:

@Repository
public class EmployeeDAOImpl implements EmployeeDAO {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public Employee getEmployee(int id) {
        Criteria query = sessionFactory.getCurrentSession().createCriteria(Employee.class);
        query.add(Restrictions.idEq(id));
        return (Employee) query.uniqueResult();
    }
}

SQL输出如下:

[junit]     /* criteria query */ select
[junit]         this_.id as id1_1_1_,
[junit]         this_.name as name2_1_1_,
[junit]         this_.supervisorId as supervis3_1_1_,
[junit]         employeesu2_.id as id1_0_0_,
[junit]         employeesu2_.name as name2_0_0_ 
[junit]     from
[junit]         Employee this_ 
[junit]     left outer join
[junit]         EMPLOYEE_SUPERVISOR employeesu2_ 
[junit]             on this_.supervisorId=employeesu2_.id 
[junit]     where
[junit]         this_.id = ? 01:23:54:0.668 
[junit] binding parameter [1] as [INTEGER] - 5 01:23:54:0.671 

[junit]     /* criteria query */ select
[junit]         this_.id as id1_1_1_,
[junit]         this_.name as name2_1_1_,
[junit]         this_.supervisorId as supervis3_1_1_,
[junit]         employeesu2_.id as id1_0_0_,
[junit]         employeesu2_.name as name2_0_0_ 
[junit]     from
[junit]         Employee this_ 
[junit]     left outer join
[junit]         EMPLOYEE_SUPERVISOR employeesu2_ 
[junit]             on this_.supervisorId=employeesu2_.id 
[junit]     where
[junit]         this_.id = ? 01:23:54:0.704 
[junit] binding parameter [1] as [INTEGER] - 6 01:23:54:0.704 

应该注意的是,默认情况下 Hibernate 似乎急切地获取这些实体并使用 LEFT OUTER JOIN 来执行此操作。但是,如果您尝试将默认获取类型设置为FetchType.LAZY然后连接类型更改为FetchMode.SELECT并且只为员工发出一个选择,而不选择主管。

Setting FetchType.LAZY with @Fetch(FetchMode.JOIN)但是,它会覆盖您的惰性获取并使用连接来急切地获取您的主管。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 @OneToOne 和 @OneToMany 时如何使 Hibernate OUTER JOIN 的相关文章

随机推荐

  • 具有多列 data.frames 的两个列表的条件匹配

    我有一个 data frames 列表 每个 data frames 中有多个列 每个 data frame 都有相同的结构 此外 我还有另一个包含多个 data frames 的列表 假设这是两个列表 firstlist lt list
  • Gnu Parallel:嵌套并行

    是否可以在由 gnu parallel 生成的脚本的多次运行中调用 gnu parallel 我有一个运行了 100 秒的 python 脚本顺序的迭代 并且在每次迭代中的某个位置 并行计算 4 个值 使用 gnu 并行 现在我想再次使用
  • 如何在ipython笔记本中设置matplotlib图形默认大小?

    我使用 ipython Notebook pylab inline 来启动 ipython Notebook 显示的 matplotlib 图形尺寸对我来说太大了 我必须手动调整它 如何设置单元格中显示的图形的默认大小 对我来说就像一个魅力
  • 不允许使用字符串类型(在“id”处,值为“@id/bAdd”)

    我收到一条错误消息不允许使用字符串类型 在 id 处 值为 id bAdd 我已经清理了该项目 早些时候一切都正常 我不知道发生了什么 导致了这个错误
  • 如何读取txt文件并将其保存在html中的javascript数组中

    有很多解决方案 但我在 html 网页上的 javascript 中发现很少或根本没有 我的html 文件所在的位置有一个名为sample txt 的数据文件 我的目标是将 txt 文件加载到数组中 该数组可用于创建表格并显示在 html
  • 如何将Entity框架中的DbSet转换为ObjectQuery

    我正在使用 Code First 方法 并遇到一个需要将 DbSet 转换为 ObjectQuery 的问题 这就是我为转换所做的 ObjectContext objectContext IObjectContextAdapter db O
  • 在 C# 中为 0x80000000 == 2147483648,但在 VB.NET 中则不然

    In C 0x80000000 2147483648 outputs True 在 VB NET 中 H80000000 2147483648 outputs False 这怎么可能 这与语言背后的历史有关 C 始终支持无符号整数 您使用的
  • DB2 时间戳选择语句

    我正在尝试运行一个简单的查询 该查询根据时间戳获取数据 如下所示 SELECT FROM
  • C#:无法以编程方式填充 DataGridView

    我没有使用设计器 而是尝试以编程方式填充我放在 Winform 上的 DataGridView 当我查看调试器下的表格时 它具有正确的列和行数 问题是网格在我的表单上显示为空的灰色框 当我通过 VS 2008 Designer 将网格绑定到
  • 禁用 WPF 标签加速键(缺少文本下划线)

    我正在设置 ContentLabel 的值包含下划线的字符串 第一个下划线被解释为加速键 不更改底层字符串 通过替换所有 with 有没有办法禁用标签的加速器 如果您使用 TextBlock 作为标签的内容 则其文本将不会吸收下划线
  • 循环和递归之间的实际区别是什么

    我目前正在使用 PHP 工作 因此这个示例将使用 PHP 但问题适用于多种语言 我正在和我的一个朋友一起做这个项目 和往常一样 我们遇到了一个大问题 现在我们俩都回家了 无法解决问题 那天晚上我们都找到了解决办法 只是我用了循环来解决问题
  • Swift - 在带有可选参数的泛型函数中以 Nil 作为参数

    我正在尝试创建一个可以接受可选参数的通用函数 这是我到目前为止所拥有的 func somethingGeneric
  • 健全性检查:作为主键浮动?

    我正在使用旧的 sql server 2000 数据库 将其中的一些信息与我正在构建的新应用程序混合在一起 我注意到几个表中的一些主键是浮点数而不是任何类型的整数 它们不是外键并且都是唯一的 我想不出有任何理由让任何人想要让他们的唯一主键
  • 使用 Python 和 Selenium 抓取图形上的悬停

    我正在尝试从中抓取数据http fuelinsights gasbuddy com Charts http fuelinsights gasbuddy com Charts使用Python和Selenium 困难的部分是 只有当鼠标悬停在折
  • Spotify 应用程序请求授权

    我正在尝试使用以下代码从 Spotify 获取 访问令牌 var encoded btoa client id client secret function myOnClick console log clikced ajax url ht
  • iTextSharp 许可 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我们想在我们的一个项目中使用 iTextSharp DLL 来提取 PDF 文本 但我第二次考虑将其发布
  • iOS9 上的 Admob 和插页式广告

    今天我注册了 adMob 并开始在我的应用程序中处理 adMob 广告 第一个是游戏 带有视图控制器 我想在游戏结束后立即显示插页式广告 所以我想在游戏结束后立即加载插页式广告游戏结束加载的视图 此视图仅在游戏结束后才可访问 并且游戏持续一
  • 对数组中的对象执行块操作并在全部完成时完成

    我有一个对象数组 我想对其执行块操作 我不确定执行此操作的最佳方法 我正在做类似下面代码的事情 但我认为这不是最佳实践 进行此类操作的最佳方法是什么 void performBlockOnAllObjects NSArray objects
  • 类不符合RequestRetrier协议

    我一直在将我的项目迁移到 swift3 并一直在努力让 Alamofire RequestRetrier 协议正常工作 我遵循 Alamofire 4 0 迁移指南 https github com Alamofire Alamofire
  • 使用 @OneToOne 和 @OneToMany 时如何使 Hibernate OUTER JOIN

    假设我有一张名为employee与领域employee id name and supervisor id and employee supervisor与领域supervisor id and name 存在外键关系employee an