Hibernate (四)
1 懒加载 (感觉用处不是很大)
- 需要的时候加载,不需要的时候就不加载。
1.1 环境的搭建
- hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--
一个sessionFactory就代表一个数据库的描述
-->
<session-factory>
<!-- 链接数据库的用户名 -->
<property name="connection.username">root</property>
<!-- 链接数据库的密码 -->
<property name="connection.password">root</property>
<!-- 链接数据库的驱动 -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- 链接数据库的url -->
<property name="connection.url">
jdbc:mysql://localhost:3306/hibernate
</property>
<!--
方言
告诉hibernate用什么样的数据库,将来会生成什么样的sql语句
-->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!--
hibernate对表的策略
validate 在hibernate容器启动的时候,根据映射文件和持久化类校验表
create 每次当hibernate启动的时候,都会根据持久化类和映射文件创建表
create-drop 每次当hibernate启动的时候,都会根据持久化类和映射文件创建表,销毁的时候删除表
update 检查,如果和映射文件不一致,则更新表的结构,如果没有表,则会创建表
-->
<property name="hbm2ddl.auto">update</property>
<!--
显示sql语句
-->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="current_session_context_class">thread</property>
<mapping resource="com/xuweiwei/vo/Classes.hbm.xml"/>
<mapping resource="com/xuweiwei/vo/Student.hbm.xml"/>
</session-factory>
</hibernate-configuration>
- Classes.java
package com.xuweiwei.vo;
import java.io.Serializable;
import java.util.Set;
/**
* 班级
*/
public class Classes implements Serializable{
private Long cid;
private String name;
private String description;
private Set<Student> students ;
public Long getCid() {
return cid;
}
public void setCid(Long cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
@Override
public String toString() {
return "Classes{" +
"cid=" + cid +
", name='" + name + '\'' +
", description='" + description + '\'' +
", students=" + students +
'}';
}
}
- Classes.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" >
<id name="cid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<set name="students" cascade="save-update" inverse="false">
<key>
<column name="cid"/>
</key>
<one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
- Student.java
package com.xuweiwei.vo;
import java.io.Serializable;
/**
* 学生
*/
public class Student implements Serializable{
private Long sid;
private String name;
private String description;
private Classes classes;
public Long getSid() {
return sid;
}
public void setSid(Long sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Classes getClasses() {
return classes;
}
public void setClasses(Classes classes) {
this.classes = classes;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", name='" + name + '\'' +
", description='" + description + '\'' +
'}';
}
}
- Student..hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Student">
<id name="sid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<many-to-one name="classes" column="cid" class="com.xuweiwei.vo.Classes"/>
</class>
</hibernate-mapping>
1.2 类的延迟加载
- 示例:使用load方法
@Test
public void testLoad(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Classes classes1 = (Classes) session.load(Classes.class,1L);
System.out.println(classes1);
session.close();
}
- 示例:在映射文件上的class元素上配置lazy属性
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" lazy="false" >
<id name="cid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<set name="students" cascade="save-update" inverse="false">
<key>
<column name="cid"/>
</key>
<one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
1.3 集合的延迟加载
1.3.1 lazy="true"
- 默认情况下,集合就是延迟加载。
- 只有当遍历集合中的元素的时候,才发出查询SQL
@Test
public void testCollectionLazy(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Classes classes = (Classes) session.get(Classes.class,1L);
Set<Student> students = classes.getStudents();
for(Student s : students){
System.out.println(s);
}
session.close();
}
1.3.2 lazy="false"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" >
<id name="cid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<set name="students" cascade="save-update" inverse="false" lazy="false" >
<key>
<column name="cid"/>
</key>
<one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
@Test
public void testCollectionLazy(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Classes classes = (Classes) session.get(Classes.class,1L);
Set<Student> students = classes.getStudents();
for(Student s : students){
System.out.println(s);
}
session.close();
}
- 当查询班级的同时查询班级下的所有学生信息。
1.3.3 lazy="extra" 更进一步
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" >
<id name="cid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<set name="students" cascade="save-update" inverse="false" lazy="extra" >
<key>
<column name="cid"/>
</key>
<one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
@Test
public void testCollectionLazy(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Classes classes = (Classes) session.get(Classes.class,1L);
System.out.println(classes.getStudents().size());
session.close();
}
- 查询的SQL如下:

1.4 延迟加载的总结
- 延迟加载(懒加载)就是通过控制发出SQL的时间来提升效率的。
2 抓取策略fetch
- fetch="select",默认
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" >
<id name="cid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<set name="students" cascade="save-update" inverse="false" fetch="select" >
<key>
<column name="cid"/>
</key>
<one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
- 示例:查询所有的班级以及班级下面的所有学生(会引起N+1问题)
@Test
public void testCollection(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Classes classes1 = (Classes) session.load(Classes.class,1L);
session.close();
System.out.println(classes1.getName());
}
- 所谓的N+1问题:
- 1:就是Hibernate在查询所有的班级的信息,直接通过select * from classes
- N:就是Hibernate通过外键,到student表中查询,比如classes表中有4条数据,那么Hibernate会这样发出SQL语句:select * from student where cid = 1;select * from student where cid =2;……
- 所谓的N+1问题:
- 其实:在查询所有班级的信息的同时查询班级下面的所有学生的信息,一般我们写SQL会这样写
SELECT s.* FROM student s WHERE s.`cid` 、IN (SELECT cid FROM classes);
- 这是个子查询。所以fetch应该是"subselect"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" >
<id name="cid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<set name="students" cascade="save-update" inverse="false" fetch="subselect" >
<key>
<column name="cid"/>
</key>
<one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
/**
* 查询所有的班级以及班级下面的所有学生
*/
@Test
public void testClassesAndStudent(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
//查询所有的班级以及所有的学生
List<Classes> classesList = session.createQuery("from Classes").list();
System.out.println(classesList);
for(Classes classes : classesList){
Set<Student> students = classes.getStudents();
for(Student student : students){
System.out.println(student);
}
}
session.close();
}
- 所以,如果是子查询,fetch="subselect"效率高点。
- 示例:如果我们需要查询班级为1号的信息和1号班级下的所有学生的信息,那么我们一般是这些写SQL的
SELECT c.*,s.* FROM classes c LEFT OUTER JOIN student s ON c.cid = s.cid
- 所以,这个时候,fetch要设置为join
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xuweiwei.vo.Classes" >
<id name="cid">
<generator class="increment"/>
</id>
<property name="name"/>
<property name="description"/>
<set name="students" cascade="save-update" inverse="false" fetch="join" >
<key>
<column name="cid"/>
</key>
<one-to-many class="com.xuweiwei.vo.Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
@Test
public void testOneClassesAndStudents(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Classes Classes = (Classes) session.get(Classes.class,1L);
Set<Student> students = Classes.getStudents();
for(Student student : students){
System.out.println(student);
}
session.close();
}
3 lazy和fetch
- 当fetch为join,我们知道Hibernate是直接发出SQL查询的,所以lazy不会起作用的。
- 当fetch为select,先加载classes后加载student,而lazy决定什么时候加载student。
4 HQL(Hibernate Query Language)
4.1 单表的HQL
- 示例:查询所有班级的信息
/**
* 查询所有的班级
*/
@Test
public void testQueryClasses(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Classes> classesList = session.createQuery("from Classes").list() ;
session.close();
}
- 示例:查询班级的名称和描述信息
/**
* 查询所有班级的名称和描述信息
*/
@Test
public void testQueryClassesNameAndDescription(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Object[]> list = session.createQuery("select name,description from Classes").list() ;
session.close();
}
- 示例:根据cid查询班级信息
/**
* 根据cid查询班级信息
*/
@Test
public void testQueryClassesByCid(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Classes> classesList = session.createQuery("from Classes where cid = ?").setParameter(0,1L).list();
for(Classes c:classesList){
System.out.println(c);
}
session.close();
}
- 示例:根据cid查询班级的信息
/**
* 根据cid查询班级信息
*/
@Test
public void testQueryClassesByCid(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Classes> classesList = session.createQuery("from Classes where cid =:cid ").setParameter("cid",1L).list();
for(Classes c:classesList){
System.out.println(c);
}
session.close();
}
- 示例:查询班级的个数
/**
* 查询班级的个数
*/
@Test
public void testCount(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Object object = session.createQuery("select count(*) from Classes").uniqueResult();
System.out.println(object);
session.close();
}
- 示例:查询主键的最大值
/**
* 查询cid的最大值
*/
@Test
public void testSelectMaxCid(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Long max = (Long) session.createQuery("select max(cid) from Classes").uniqueResult();
System.out.println(max);
session.close();
}
4.2 多表的HQL
- 内连接
/**
* 内连接
*/
@Test
public void testEq(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Object[]> list = session.createQuery("from Classes c ,Student s where c.cid = s.classes.cid").list();
session.close();
}
- 示例:内连接
@Test
public void testInnerJoin(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Object[]> list = session.createQuery("from Classes c inner join c.students s").list();
session.close();
}
- 示例:左外连接
@Test
public void testLeftOuterJoin(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Object[]> list = session.createQuery("from Classes c left outer join c.students s").list();
session.close();
}
- 示例:迫切左外连接
@Test
public void testLleftOuterJoinFetch(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Classes> list = session.createQuery("from Classes c left outer join fetch c.students s").list();
session.close();
}
- 示例:迫切内连接
@Test
public void testInnerJoinFetch(){
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
List<Classes> list = session.createQuery("from Classes c inner join fetch c.students s").list();
session.close();
}
Hibernate (四)的更多相关文章
- hibernate(四) 双向多对多映射关系
序言 莫名长了几颗痘,真TM疼,可能是现在运动太少了,天天对着电脑,决定了,今天下午花两小时去跑步了, 现在继上一章节的一对多的映射关系讲解后,今天来讲讲多对多的映射关系把,明白了一对多,多对多个人感 ...
- Hibernate(四)之对象状态及一级缓存
一.Hibernate中的对象状态 1.1.瞬时态(临时态) 没有与Hibernate产生关联 与数据库中的记录没有产生关联(有关联就是与数据库中表的id相对应) 获得:一般都只直接创建(new) 瞬 ...
- Hibernate(四)结构-基础语义和事务
一.基础语义 核心: Configuration SessionFactory Session 二.Configuration Configuration类负责管理Hibernate的配置信息,Hib ...
- hibernate(四)__由表逆向创建Domain对象和对象关系映射文件
之前我们是手写Domain对象和对象关系映射文件->然后生成数据库中的Table. 现在我们反过来先在数据库中建好Table->然后用工具生成Domain对象和对象关系映射文件. 步骤: ...
- Hibernate四 批量处理
Hibernate批量处理一 批量插入将很多条记录插入数据库时,Hibernate通常会采用以下做法:public void test() { for(int i=0;i<1000;i++){ ...
- Hibernate(四)——缓存策略+lazy
Hibernate作为和数据库数据打交道的框架,自然会设计到操作数据的效率问题,而对于一些频繁操作的数据,缓存策略就是提高其性能一种重要手段,而Hibernate框架是支持缓存的,而且支持一级和二级两 ...
- ORM框架Hibernate (四) 一对一单向、双向关联映射
简介 在上一篇博客说了一下多对一映射,这里再说一下一对一关联映射,这种例子在生活中很常见,比如一个人的信息和他的身份证是一对一.又如一夫一妻制等等. 记得在Java编程思想上第一句话是“一切皆对象”, ...
- ssh架构之hibernate(四)二级缓存
二级缓存使用步骤: 1.拷贝jar包 2.配置Hibernate.cfg.xml文件 a.#开启二级缓存 hibernate.cache.use_second_level_cache=true b.# ...
- Hibernate(四)
==================================投影(查询)=============================投影查询:查询一个持久化类的一个或多个属性值 1.将每条 ...
- Hibernate(四)--延迟加载(lazyload)
hibernate中的延迟加载(lazyload)分属性的延迟加载和关系的延迟加载 属性的延迟加载: 当使用load的方式来获取对象的时候,只有访问了这个对象的属性,hibernate才会到数据库中进 ...
随机推荐
- 解决打开png图片黑屏问题(批量还原Xcode优化后的png)
window 打开Xcode 里面的png图片会黑屏,但是在mac 打开就显示正常, 这是因为Xocde里面的png图片被 pngcrush 优化过了,需要还原它的优化,window 平台才可以打开. ...
- 关于乱序(shuffle)与随机采样(sample)的一点探究
最近一个月的时间,基本上都在加班加点的写业务,在写代码的时候,也遇到了一个有趣的问题,值得记录一下. 简单来说,需求是从一个字典(python dict)中随机选出K个满足条件的key.代码如下(py ...
- linux几条常用的命令
列出一些手头分分钟要用到的命令. 1.df -h 用来查看各个分区的大小 2.du -h --max-depth=0 /data2/xijun.gong/tt_data 用来查看文件夹的大小,并指定递 ...
- Python 之 基础知识(一)
首先,对于初学者在一个项目中设置多个程序可以执行,是非常方便的,可以方便对不同知识点的练习和测试 对于商业项目而言,通常在一个项目中,只有一个可以执行的Python程序 一.注释 为了提高可读性,注释 ...
- cs231n spring 2017 lecture10 Recurrent Neural Networks 听课笔记
(没太听明白,下次重新听一遍) 1. Recurrent Neural Networks
- 【干货分享】dos命令大全
一般来说dos命令都是在dos程序中进行的,如果电脑中安装有dos程序可以从开机选项中选择进入,在windows 系统中我们还可以从开始运行中输入cmd命令进入操作系统中的dos命令,如下图: 严格的 ...
- BZOJ 2219: 数论之神
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2219 N次剩余+CRT... 就是各种奇怪的分类讨论.. #include<cstrin ...
- UnityShader 表面着色器简单例程集合
0.前言 这些简单的shader程序都是写于2015年的暑假.当时实验室空调坏了,30多个人在实验室中挥汗如雨,闷热中学习shader的日子还历历在目.这些文章闲置在我个人博客中,一年将过,师弟也到了 ...
- 使用parcel打造一个零配置的react工作流
parcel是一个前端打包工具.因其推崇的零配置理念,和webpack形成了鲜明对比.对于我这样一个被后端IDE智能提示宠坏的猿,自然是对webpack提不起爱.平时也都是使用CLI默认配置好webp ...
- 6.移植uboot-支持yaffs烧写,打补丁
在上一章,裁剪uboot以及分区后,本章主要使uboot支持yaffs以及制作补丁 1. 修改uboot支持yaffs 首先,每个命令都会对应一个文件,比如nand命令对应的common/cmd_na ...