Hibernate 数据获取类型问题
Hibernate data fetch type issues
我会这样解释场景:
我有一个数据库,其中有一些 tables
- Activity
- 运动
- 领悟[=67=]
- 问题
- 句子
这里是描述关系的最佳方式,
- Activity 有一组练习。
- 练习有一组问题。
- 每个练习都有一个理解
- 每个问题都有一组句子。
这是我尝试在休眠中实现的方式:
public Exercise getActivityById(int ActivityId)
{
Session session = HibernateUtil.getSessionFactory().openSession();
Activity a = (Activity)session.get(Activity.class, ActivityId);
session.close();
return a;
}
public List<Exercise> getExercisesFromActivity(Activity a)
{
Session session = HibernateUtil.getSessionFactory().openSession();
List<Exercise> e = a.getExercises();
session.close();
return e;
}
public Comprehension getComprehensionFromExercise(Exercise e)
{
Session session = HibernateUtil.getSessionFactory().openSession();
Comprehension c = e.getComprehension();
session.close();
return c;
}
//...... and so on
// i will call like this
Activity a = getActivityById(23);
List<Exercise> e = a.getExercisesFromActivity(a);
Comprehension c = getComprehension(e.get(0));
//.... and so on
基本上,我正在努力遵循最佳实践,即 每个查询的会话。在这种方法中,我得到了 异常 LazyInitializationException ,因为对象已经分离了。
所以,我用谷歌搜索了所有内容,发现我可以尝试 4 种解决方案,我在多个网站上都找到了相同的东西。
http://uaihebert.com/four-solutions-to-the-lazyinitializationexception/
其中,如果我尝试制作 **default-lazy=false 或在视图中打开会话(视图中的事务)都是不好的做法。**
如果我使用 Join 查询,我认为它在两个方面违反了:
如果数据库很大,我们有几个 table 要加入,在我的场景中,根据我的理解,我将不得不加入
Activity
锻炼
理解
问题
句子
.........
和更多 tables,如果我必须在单连接查询中做。
2. 它不会破坏每个查询 会话 吗? ,我们在单个会话中要求太多。作为 jdbc 用户,我曾经触发单个 SQL 查询来逐一获取所有内容。一个连接将帮助我获取一个 table 数据。
3. 如果这是正确的,那么所有企业应用程序都需要加入 n 个 tables 才能使用休眠和集合,这显然是最糟糕的事情。
所以,最后,问题出现了,我该如何处理这种情况。什么是最佳实践。我问过一个人,他是这样说的
public void getEverything()
{
Session session = HibernateUtil.getSessionFactory().openSession();
Activity a = (Activity)session.get(Activity.class, ActivityId);
List<Exercises> e = a.getExercises();
Comprehension c = e.get(0).getComprehension();
List<Question> q = e.get(0).getQuestions();
ApplicationWidePojo apojo = new ApplicationWidePojo();
// set all the tables , values in this pojo
session.close
}
// this eliminated lazyinitializationexception
但我认为这不是每个查询的会话。或者细粒度
另外,还有一个问题。我应该使用一个 pojo 来设置整个数据并在应用程序范围内使用吗?这种方式还有其他好的选择吗?
session-per-query 是一个反模式。您应该:
- 每笔交易使用一个会话
- 在多个事务上延长会话
如果您有一个带有 multiple children levels 的根实体,您需要颠倒查询并从最内层的子实体获取到根实体:
select q
from Question q
join fetch q.exercise e
join fetch e.activity a
where a.id = :activityId
此查询将毫无疑问地过滤掉 activities/exercises,但这在您的用例中可能没问题。
我会这样解释场景:
我有一个数据库,其中有一些 tables
- Activity
- 运动
- 领悟[=67=]
- 问题
- 句子
这里是描述关系的最佳方式,
- Activity 有一组练习。
- 练习有一组问题。
- 每个练习都有一个理解
- 每个问题都有一组句子。
这是我尝试在休眠中实现的方式:
public Exercise getActivityById(int ActivityId)
{
Session session = HibernateUtil.getSessionFactory().openSession();
Activity a = (Activity)session.get(Activity.class, ActivityId);
session.close();
return a;
}
public List<Exercise> getExercisesFromActivity(Activity a)
{
Session session = HibernateUtil.getSessionFactory().openSession();
List<Exercise> e = a.getExercises();
session.close();
return e;
}
public Comprehension getComprehensionFromExercise(Exercise e)
{
Session session = HibernateUtil.getSessionFactory().openSession();
Comprehension c = e.getComprehension();
session.close();
return c;
}
//...... and so on
// i will call like this
Activity a = getActivityById(23);
List<Exercise> e = a.getExercisesFromActivity(a);
Comprehension c = getComprehension(e.get(0));
//.... and so on
基本上,我正在努力遵循最佳实践,即 每个查询的会话。在这种方法中,我得到了 异常 LazyInitializationException ,因为对象已经分离了。
所以,我用谷歌搜索了所有内容,发现我可以尝试 4 种解决方案,我在多个网站上都找到了相同的东西。
http://uaihebert.com/four-solutions-to-the-lazyinitializationexception/
其中,如果我尝试制作 **default-lazy=false 或在视图中打开会话(视图中的事务)都是不好的做法。**
如果我使用 Join 查询,我认为它在两个方面违反了:
如果数据库很大,我们有几个 table 要加入,在我的场景中,根据我的理解,我将不得不加入
Activity 锻炼 理解 问题 句子 .........
和更多 tables,如果我必须在单连接查询中做。 2. 它不会破坏每个查询 会话 吗? ,我们在单个会话中要求太多。作为 jdbc 用户,我曾经触发单个 SQL 查询来逐一获取所有内容。一个连接将帮助我获取一个 table 数据。 3. 如果这是正确的,那么所有企业应用程序都需要加入 n 个 tables 才能使用休眠和集合,这显然是最糟糕的事情。
所以,最后,问题出现了,我该如何处理这种情况。什么是最佳实践。我问过一个人,他是这样说的
public void getEverything()
{
Session session = HibernateUtil.getSessionFactory().openSession();
Activity a = (Activity)session.get(Activity.class, ActivityId);
List<Exercises> e = a.getExercises();
Comprehension c = e.get(0).getComprehension();
List<Question> q = e.get(0).getQuestions();
ApplicationWidePojo apojo = new ApplicationWidePojo();
// set all the tables , values in this pojo
session.close
}
// this eliminated lazyinitializationexception
但我认为这不是每个查询的会话。或者细粒度
另外,还有一个问题。我应该使用一个 pojo 来设置整个数据并在应用程序范围内使用吗?这种方式还有其他好的选择吗?
session-per-query 是一个反模式。您应该:
- 每笔交易使用一个会话
- 在多个事务上延长会话
如果您有一个带有 multiple children levels 的根实体,您需要颠倒查询并从最内层的子实体获取到根实体:
select q
from Question q
join fetch q.exercise e
join fetch e.activity a
where a.id = :activityId
此查询将毫无疑问地过滤掉 activities/exercises,但这在您的用例中可能没问题。