只要在HQL中指定了外连接,那么不论配置文件中是预先抓取或是立即或延迟检索,都会失效。
以上面为例:
学生对身份证采取预先抓取和立即检索,对班级是预先抓取,班级对学生是延迟加载。
Session session = SessionUtil.getSession();
Transaction tran = session.beginTransaction();
Query query = session.createQuery("from Student as s left join s.teamID");
List list = query.list();
tran.commit();
session.close();
Object st[] = (Object[])list.get(0);
Student s = (Student) st[0];
System.out.println(s.getName());
System.out.println(s.getTeamID().getName());
System.out.println(s.getTeamID().getStudents().size());
在查询的LIST中包含两个长度为2的数组,每一个数组包含两个对象,学生对象和班级对象。
打印:
1.Hibernate: select student0_.ID as ID1_0_, team1_.ID as ID0_1_, student0_.Name as Name1_0_, student0_.TeamID as TeamID1_0_, team1_.Name as Name0_1_ from test.student student0_ left outer join test.team team1_ on student0_.TeamID=team1_.ID
2.Hibernate: select card0_.ID as ID2_0_, card0_.StudentID as StudentID2_0_, card0_.Name as Name2_0_ from test.card card0_ where card0_.ID=?
3.Hibernate: select card0_.ID as ID2_0_, card0_.StudentID as StudentID2_0_, card0_.Name as Name2_0_ from test.card card0_ where card0_.ID=?
tuping
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.vo.Team.students, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)
at org.hibernate.collection.PersistentSet.size(PersistentSet.java:139)
at com.test.Client1.main(Client1.java:28)
二中
对1的解释:因为采取的是HQL中的左连接的方式,所以会忽略配置中预先抓取的方式。
对2.3的解释:在配置文件中的检索策略只能影响到session.get()或load方法,对于直接使用HQL的方式将忽略配置文件的预先抓取的检索策略,而是直接采取HQL中的方式。
1)得到学生对象以后,学生对身份证的预先抓取策略失效,二是采取的是立即加载得到身份证。
2)得到班级对象以后,由于班级对学生采用了延迟加载(这个策略将不会忽略),于是班级的学生集合并没有得到初始化。所以才打印出例外。
将班级对学生的加载方式改为立即加载就OK了。
打印:
1.Hibernate: select student0_.ID as ID1_0_, team1_.ID as ID0_1_, student0_.Name as Name1_0_, student0_.TeamID as TeamID1_0_, team1_.Name as Name0_1_ from test.student student0_ left outer join test.team team1_ on student0_.TeamID=team1_.ID
2.Hibernate: select card0_.ID as ID2_0_, card0_.StudentID as StudentID2_0_, card0_.Name as Name2_0_ from test.card card0_ where card0_.ID=?
3.Hibernate: select card0_.ID as ID2_0_, card0_.StudentID as StudentID2_0_, card0_.Name as Name2_0_ from test.card card0_ where card0_.ID=?
4.Hibernate: select students0_.teamID as teamID3_, students0_.ID as ID3_, students0_.ID as ID1_2_, students0_.Name as Name1_2_, students0_.TeamID as TeamID1_2_, team1_.ID as ID0_0_, team1_.Name as Name0_0_, card2_.ID as ID2_1_, card2_.StudentID as StudentID2_1_, card2_.Name as Name2_1_ from test.student students0_ left outer join test.team team1_ on students0_.TeamID=team1_.ID left outer join test.card card2_ on students0_.ID=card2_.ID where students0_.teamID=?
tuping
二中
2
这里有个疑问,因为第2.3已经得到了CARD的对象,为什么第4句还要去数据库取一次数据。这是因为第一次发送SQL语句从数据库取身份证对象时,学生对身份证采取的是预先抓取被忽略,所以采取了立即加载的策略。
而班级对学生采用HQL指定的左连接取得对象。
虽然班级和学生对象都取得了。但是由于集合的特殊性,还需要取得集合对学生对象的引用。由于学生对身份证采取的是预先抓取,所有才会有第4句。
如果在语句中改用Fetch进行连接
Session session = SessionUtil.getSession();
Transaction tran = session.beginTransaction();
Query query = session.createQuery("from Student as s left join fetch s.teamID");
List list = query.list();
tran.commit();
session.close();
// Object st[] = (Object[])list.get(0);这种得到对象的方式就是错的。
//Student s = (Student) st[0];
//通过查询虽然与上面生成的SQL语句是一样的,但是再内存中得到的对象却发生了变化。此时检索出来的是两个学生元素。所以通过LIST得到的集合是学生的集合。
Student s = (Student) list.get(0);
System.out.println(s.getName());
System.out.println(s.getTeamID().getName());
System.out.println(s.getTeamID().getStudents().size());
HQL忽略配置文件预先抓取的深度。
如果HQL语句中出现了外连接from Team t left outer join t.students
则班级对学生的预先抓取的策略将被HQL指定的左外连接所覆盖。
举例:
学生对身份证采取预先抓取和立即加载,学生对班级采取预先抓取,班级对学生采取预先抓取和延迟检索。
通过查寻得到的结果是学生对身份证的预先抓取也被忽略了。HQL忽略配置文件预先抓取策略深度就是HQL语句中指定的对象,HIBERNATE对这些对象直接的属性配置忽略预先抓取,采取立即或延迟检索的策略。假设身份证还关联其他对象,则这些对象的抓取策略按照配置文件的设定,预先抓取不会被忽略。
总结:
1.仅仅从使用角度来看,预先抓取和立即检索的效果一样,只不过预先抓取可以减少SQL语句条数。
2.预先抓取的关键字是JOIN和FETCH,而外连接的关键字是JOIN
3.预先抓取将初始化代理对象的引用,吧对象的数据填充完毕,但是外连接只是把对象组装好,不会初始化对象之间的引用关系。
分享到:
相关推荐
- **数据冗余**:预先抓取(Eager Loading)策略通常会一次性加载所有相关联的实体,即使其中部分实体在当前业务场景中并不需要使用。这种做法会导致不必要的数据冗余。 - **灵活性受限**:预先抓取策略使得开发人员...
首先,adb是一个多功能的命令行工具,它是Android SDK的一部分,用于连接开发者计算机和Android设备,进行数据传输、设备控制、日志抓取等操作。在本例中,标签"adb logcat"表明我们关注的是通过adb执行的logcat命令...
- **并行抓取**:为了提高效率,可以开启多个线程同时抓取不同的URL,但要注意防止对服务器造成过大压力。 - **线程安全**:确保在多线程环境下正确同步访问数据库连接或其他共享资源。 9. **持续运行与调度**: ...
在IT领域,网络数据包抓取是网络诊断和分析的重要技术。C#是一种广泛用于开发Windows应用程序的编程语言,它可以用来构建强大的网络工具,包括抓取TCP和UDP网络数据包。下面将详细介绍如何使用C#进行网络数据包捕获...
这个类可能封装了建立连接、发送GET或POST请求、处理响应头和获取响应体的过程。它也可能支持处理cookies、重定向以及设置请求头等特性,这些都是网络爬虫经常需要的功能。 `ChunkedInputStream.java` 文件则可能是...
3. **添加外部依赖库**:根据项目需求,将预先定义好的类库添加到`WEB-INF\lib`文件夹中。 4. **配置`web.xml`文件**:复制`tomcat\conf\web.xml`中的相关配置内容到当前项目的`web.xml`文件中。 5. **编写`...
1. 初始化:连接到NAO的控制服务器,设置机器人状态,并加载必要的模块。 2. 目标检测:使用摄像头捕获图像,通过图像处理算法(如OpenCV)识别目标物体。 3. 距离测量:结合超声波传感器数据,确定与目标的距离,...
当Web Role出现故障时,除了排查Azure平台本身的问题外,还需要检查IIS服务的状态。其中,通过抓取IIS的Dump文件是一种非常有效的方法,可以帮助开发者定位问题所在。 #### 问题症状 当排除了Azure平台的问题后,...
7. **Connection**: 控制连接行为,如 "keep-alive" 表示希望保持连接持续,避免每次请求都创建新的连接。 开发这样一个应用,你需要熟悉Java Servlet API,包括HttpServletRequest对象,它是处理HTTP请求的核心...
线程池是由一组预先创建的线程组成的,这些线程可以复用,而不是每次执行任务时都创建新的线程。`ThreadPoolExecutor`是Java并发包`java.util.concurrent`中的核心类,用于实现线程池服务。通过设置线程池参数,我们...
在处理大量数据时,预先计算数据库中的总记录数是非常实用且高效的编程技巧之一。这样做可以帮助我们更好地组织数据展示逻辑,尤其是在分页查询、数据统计等方面。 #### 实现方法 - **SQL语句**: 使用`COUNT(*)`...
本课题的主要目的是设计面向...对网络爬虫的连接网络设置连接及读取时 间,避免无限制的等待。为了适应不同需求,使网络爬虫可以根据预先设定的主 题实现对特定主题的爬取。研究网络爬虫的原理并实现爬虫的相关功能。
2. **转换并重定向**:然后根据预先设定的规则对原始URL进行转换,并将其重定向到新的URL地址。 ### 五、示例代码 下面提供一个简单的Apache `.htaccess`文件示例,演示如何实现URL重写: ```apacheconf ...
4. 数据清洗:对抓取到的信息进行预处理,如去除HTML标签、处理异常值等。 5. 存储数据:使用数据库API连接Access,将清洗后的数据插入到指定表中。 6. 错误处理:设置异常处理机制,确保程序在遇到错误时能继续运行...
仿生机器人方面,研究者们主要集中于对人行走时的步态分析,通过对人脚形状的分析,得出具有圆形截面的脚趾和脚后跟以及具有扁平截面的连接脚趾和脚后跟的中间部分具有最佳的动力学性能。 Xia Zeyang 等人提出了一种...
把握器是设备的控制中心,包括把握运算单元和面板操作单元,可以预先编程,对整个生产过程进行自动化控制,减少人工操作,提高设备的自动化程度,同时降低了对工作人员技能的要求。 从附图中可以看出,设备的各个...
对网络爬虫的连接网络设置连接及读取时间,避免无限制的等待。为了适应不同需求,使网络爬虫可以根据预先设定的主题实现对特定主题的爬取。研究网络爬虫的原理并实现爬虫的相关功能,并将爬去的数据清洗之后存入...
在这里,当抓取程序发现新的帖子时,它会通过Webhook将帖子的摘要和链接发送到预先配置的Discord频道。 要适应这个机器人以满足自己的需求,你需要了解Python编程基础,以及如何使用上述的Web抓取库。可能需要修改...
同样,可以在集合级别定义批量抓取,预先加载整个集合,避免多次数据库交互。 5. **子查询抓取(Subselect Fetching)**: 当需要抓取延迟加载的集合或单值代理时,Hibernate会使用子查询一次性加载所有实例。这种...