Java 会话关闭后,如何禁用或阻止使用Hibernate代理?

Java 会话关闭后,如何禁用或阻止使用Hibernate代理?,java,hibernate,jdbc,Java,Hibernate,Jdbc,因此,我现在正在开发一个RESTful API,它充当客户端和数据库之间的一个层,我目前正在使用Hibernate for ORM,几天来我一直在尝试找到问题的解决方案,到处搜索都没有用 我不能发布我正在使用的实际代码,因为它太大了,但是想象一下: 我有一个类Employee映射为如下所示的Hibernate实体 @实体 公营雇员{ @身份证 整数id; 字符串名; 双薪; 弦乐部; @manytone(fetch=FetchType.LAZY) @JoinColumn(name=“公司id”)

因此,我现在正在开发一个RESTful API,它充当客户端和数据库之间的一个层,我目前正在使用Hibernate for ORM,几天来我一直在尝试找到问题的解决方案,到处搜索都没有用

我不能发布我正在使用的实际代码,因为它太大了,但是想象一下:

我有一个类
Employee
映射为如下所示的Hibernate实体

@实体
公营雇员{
@身份证
整数id;
字符串名;
双薪;
弦乐部;
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“公司id”)
公司;
//获得者/接受者
@凌驾
公共字符串toString(){
返回“雇员{”+
“id=”+id+
“,name=”“+name+”\“””+
“,salary=“+salary+
“,部门=”+部门+“\”+
“,company=“+公司+
'}';
}
}
还有另一个实体类
Company
,如下所示:

Employee:
| id | name     | salary | department | company_id |
|----|----------|--------|------------|------------|
| 1  | john doe | 3000   | Finance    | 1          |
| 2  | mary sue | 3300   | HR         | 1          |

Company:
| id | name | address    |
|----|------|------------|
| 1  | ACME | St. Sesame |
Employee{id=1,name='john doe',salary=3000.0,department='Finance',company=Company{id=1,name=null,address=null,employees=null}}
@实体
公营公司{
@身份证
整数id;
字符串名;
字符串地址;
@OneToMany(mappedBy=“company”,fetch=FetchType.LAZY)
列出员工名单;
//接球手和接球手
@凌驾
公共字符串toString(){
返回“公司{”+
“id=”+id+
“,name=”“+name+”\“””+
“,地址=”“+地址+”\“””+
“,employees=“+雇员+
'}';
}
}
数据库如下所示:

Employee:
| id | name     | salary | department | company_id |
|----|----------|--------|------------|------------|
| 1  | john doe | 3000   | Finance    | 1          |
| 2  | mary sue | 3300   | HR         | 1          |

Company:
| id | name | address    |
|----|------|------------|
| 1  | ACME | St. Sesame |
Employee{id=1,name='john doe',salary=3000.0,department='Finance',company=Company{id=1,name=null,address=null,employees=null}}
现在让我们假设我想从某个员工那里获取数据,如果我以后需要公司数据,我只需要员工数据+公司ID(并且只有ID)作为参考。它看起来像这样:

Employee:
| id | name     | salary | department | company_id |
|----|----------|--------|------------|------------|
| 1  | john doe | 3000   | Finance    | 1          |
| 2  | mary sue | 3300   | HR         | 1          |

Company:
| id | name | address    |
|----|------|------------|
| 1  | ACME | St. Sesame |
Employee{id=1,name='john doe',salary=3000.0,department='Finance',company=Company{id=1,name=null,address=null,employees=null}}
Session Session=SessionManager.openSession();
Employee emp=session.get(Employee.class,1);
session.close();
现在我想显示员工数据

System.out.println(emp);
这里预期的输出(或者至少是我预期的)是这样的:

Employee:
| id | name     | salary | department | company_id |
|----|----------|--------|------------|------------|
| 1  | john doe | 3000   | Finance    | 1          |
| 2  | mary sue | 3300   | HR         | 1          |

Company:
| id | name | address    |
|----|------|------------|
| 1  | ACME | St. Sesame |
Employee{id=1,name='john doe',salary=3000.0,department='Finance',company=Company{id=1,name=null,address=null,employees=null}}
这很简单,问题是它会抛出LazyInitializationException,因为Hibernate在调用Employee的
toString()
时试图使用代理对象获取de Company数据,但会话已经关闭

问题是,如果我关闭了会话而没有获取更多的数据,那么就是这样,不再需要数据,休眠!如果我打开一个会话,我将获取我需要的所有数据,并且只获取我需要的数据,关闭会话后,这意味着我不再需要任何数据,谢谢hibernate,但hibernate的代理对象即使在会话关闭后仍保持活动状态

我搜索了整个网络,甚至在StackOverflow上,这里也有一些所谓的“解决方案”或“变通方法”,如:

  • 为什么不将HQL与构造函数一起使用?
实际上,在许多用例中,当查询足够简单,可以使用HQL时,我都会使用它们。问题是许多用例需要复杂的查询,有大量的连接和计算,甚至使用未映射到Hibernate实体的表,所以我需要一个本机查询来实现

  • 您可以将HQL与构造函数一起使用,并为需要在查询中访问的每个数据库表创建实体
这将意味着映射我将在一个,也许两个用例上使用的数十个实体,并且不再映射,这样我就可以将HQL与构造函数一起使用。此外,有些查询使用本机函数和HQL根本不支持的其他复杂计算

  • 然后使用本机查询,当您不需要该列数据时,可以将
    NULL作为columnName
我在某些用例中也这样做,问题是当该列是实体关系上的联接列时,Hibernate设置了一个代理对象,我不需要代理对象,只要联接列的数据,如果,并且只有当,代码的另一部分需要该数据,在这里,我可以打开一个新会话并检索所需的数据

  • 为什么不使用“在视图上打开会话”模式使会话保持打开状态?
不,不行,这是一个RESTful API,如果客户机在第一个请求中请求员工数据,然后以后再次请求前一个员工的公司数据,并在请求正文中传递公司ID,该怎么办?这是一个常见的用例

  • session.detach()?
不起作用

  • 无状态会话?
仍然创建代理对象,但它仅禁用当前会话的第一级和第二级缓存

  • 为什么不使用DTO?
并为我的API的部分数据请求的每个用例创建一个新类?哈哈哈

你看,我使用像Hibernate这样的ORM解决方案的唯一原因是因为我害怕手动处理结果集do DEATH。忘记HQL、Criteria API等吧。如果我只能用Hibernate将结果集映射到对象(或对象列表),那么我不介意从字符串创建本机查询。我想让Hibernate知道,如果有一个实体关系在会话关闭之前我没有获取,这意味着我不想获取它,因此没有代理对象

我知道可能还有另一个ORM解决方案没有这个问题,但是我不能给时间去学习它,因为最后期限,所以请有人帮助我

编辑

所以,你们中的一些人将我的问题标记为重复的,但有区别:

  • 这个问题围绕着如何“取消专利”