目录
0.orm思想(object relational mapping)
4.Update、Save、saveOrUpdate方法区别
6.Hibernate三种查询query/criteria/sqlquery对象的使用
7.一对多以及多对多关系的映射配置、级联保存和删除,inverse属性
10.迫切 内(左外) 连接 fetch 返回对象不是数组(Query)
11.hibernate检索策略(立即查询和延迟查询(又分两个)-->优化)
0.orm思想(object relational mapping)
orm思想是hibernate的核心思想,什么是orm思想?
1)让实体类和数据库表进行一一对应关系--->实体类和数据库表的对应、实体类属性和表的字段的对应
2)操作数据时不用操作数据库表,而是操作表对应类对象的属性(需要用到hibernate封装的session对象)
1.Hibernate的两种配置文件
1.1映射关系的配置文件
1.1.1位置和命名:
(hibernate通过核心配置文件来读取,不会直接读取,所以位置和名字可随意)
映射关系指的就是 实体类和数据库表之间的映射
*建议:在实体类所在包里面创建,命名为:实体类名称.hbm.xml
1.1.2 XML约束
使用在线读取DTD约束的方式来进行XML约束
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
1.1.3配置文件的格式
需要配置的映射关系有两个,一个是类和表的映射,一个是类属性和表字段的映射
<hibernate-mapping>
<!-- 1 配置类和表对应
class标签
name属性:实体类全路径
table属性:数据库表名称
-->
<class name="cn.itcast.entity.User" table="t_user">
<!-- 2 配置实体类id和表id对应
hibernate要求实体类有一个属性唯一值
hibernate要求表有字段作为唯一值
-->
<!-- id标签
name属性:实体类里面id属性名称
column属性:生成的表字段名称
-->
<id name="uid" column="uid">
<!-- 设置数据库表id增长策略
native:生成表id值就是主键自动增长
-->
<generator class="native"></generator>
</id>
<!-- 配置其他属性和表字段对应
name属性:实体类属性名称
column属性:生成表字段名称
-->
<property name="username" column="username"></property>
<property name="password" column="password"></property>
<property name="address" column="address"></property>
</class>
</hibernate-mapping>
1.2核心配置文件
1.2.1位置和命名
(hibernate会直接读取的,所以位置和名字规定好了)
- 位置:必须src下面
- 名称:必须hibernate.cfg.xml
1.2.2 XML约束
同样也是在线读取DTD来进行约束
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
1.2.3配置文件的格式
需要配置的有三部分:
1)数据库信息
2)hibernate信息
3)将上述的映射文件通过配置来让hibernate来读取
<hibernate-configuration>
<session-factory>
<!-- 数据库信息 必须-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_1?useUnicode=true&characterEncoding=UTF-8</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">532077936</property>
<!-- hibernate信息 可选 -->
<!-- 输出底层sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化输出的sql语句 -->
<property name="hibernate.format_sql">true</property>
<!-- 让hibernate在没有创建表且有对应实体类的时候创建表 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 配置数据库方言 比如mysql中的limit oracle中的rownum 不同的数据库用的value不同 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 将映射文件放到核心配置文件中 -->
<mapping resource="com/tencent/entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
2.Session是什么?怎么来的?
>>Session是对于hibernate开发人员一个很重要的接口,主要是用于检测持久对象的变化,并及时刷新数据库,有时候也可以叫做持久层管理器,Session是非线程安全的,所以要一个线程对应一个Session
>>Session是由SessionFactory,一般一个项目只有一个SessionFactory,是公用的
>>SessionFactory是由Configuration的对象通过configure()来创建的,通过此方法就读取了默认位置的核心配置文件
也可以通过传递参数来指定核心配置文件的位置
3.实体类对象的三种状态
1)瞬时态:对象里面没有id值,对象与session没有关联
2)持久态:对象里面有id值,对象与session关联
3)托管态:对象有id值,对象与session没有关联
4.Update、Save、saveOrUpdate方法区别
4.1 Session.update();
>>瞬时态:
无法存储,抛出异常
org.hibernate.TransientObjectException: The given object has a null identifier
>>持久态:
不修改id,就直接覆盖
修改id,
①如果id不存在抛出异常
org.hibernate.HibernateException: identifier of an instance of com.entity.User was altered from 1 to 2
②如果id存在(和之前的id不同),
也会抛出异常
org.hibernate.HibernateException: identifier of an instance of com.entity.User was altered from 1 to 297e7cba
>>托管态:
对于存在的id会以所有 实体类对象的属性值 来覆盖 原有表的对应字段
对于不存在的id不会进行任何操作
4.2 Session.save();
>>瞬时态:
创建一条新的数据,字段值 对应 类对象属性值
>>持久态:
结果同update();
>>托管态:
id不管存不存在,都将创建一条新的数据,字段值 对应 类对象属性值
4.2 Session.saveOrUpdate();
>>瞬时态:
结果同save();
>>持久态:
结果同update();
>>托管态:
结果同update();
综上实验结果,对于session取回来的持久态数据,是不能更改其id的,会抛出异常
对于持久态的数据,使用三种方法得到的结果都是一样的
当需要创建新条目的时候,需要使用save方法,不管是瞬时态还是托管态都会创建新数据(不管id是否已存在)
而需要更新条目时(不要新条目),就使用update
5.Hibernate一级缓存的内部运行方式
6.Hibernate三种查询query/criteria/sqlquery对象的使用
***这里只是举例了三种对象最简单的用法(查询表所有字段)
6.1 query
hql:hibernate query language
6.2 criteria
6.3 sqlquery
7.一对多以及多对多关系的映射配置、级联保存和删除,inverse属性
7.1一对多: 用一个外键来维系两个表
①两个实体类相互表示
eg:一个老师对应多个学生,在老师实体类中添加一个学生类的集合属性,在学生实体类添加一个老师类集合属性
②映射配置
配置每个实体类中添加的对应的属性(另一个实体类)
>>>学生表配置文件中:
<many-to-one name="teacher" class="com.entity.Teacher" column="stid">
*name属性:老师的实体类名称为Teacher,所以用teacher
*class属性:Teacher类的全路径
*column属性:外键名称
>>>老师表配置文件中:
<set name="setStudent" cascade="save-update">
<key column="stid"></key>
<one-to-many class="com.entity.Student"/>
</set>
*set的name属性:写老师类里面的学生类set集合名称
*cascade="save-update":级联保存的时候只需要将学生放到老师的学生集合下就可以了,不用再将老师放到学生的老师属性下
*column:外键名称
*class:学生类全路径
级联保存、删除 就是
比如创建一个老师,要给多个学生在老师下面,保存到数据库就是级联保存。删除也同理
Teacher tea = new Teacher();
tea.setName("李");
tea.setPhone("110");
Student stu = new Student();
stu.setStu_name("小宏");
// 把学生放到老师的学生集合下面
tea.getSetStudent().add(stu);
//如果没有cascade="save-update"
//就需要这一句stu.setTeacher(tea);
// 保存到数据库
session.save(tea);
③把映射文件引入到核心配置文件中
7.2多对多: 用一个表(由外键构成的表)来维系另外两个表
eg:一个用户有多个角色,一个角色可以由多个用户扮演
①同一对多,只不过两个实体类添加的都是对应另一个表的集合
②映射配置
user_role:由外键构成的维系 用户表 和 角色表 的第三张表
③把映射文件引入到核心配置文件中
一般都不用这种方法,因为这样第三张表只能存放两个字段(两个id)
一般都是创建多一个实体类用于当做第三张表,将多对多 变成两个一对多
7.3 inverse属性来取消双向维护,减少重复sql
在hibernate中,是双向维护外键的
(eg:一个老师对应多个学生)
在老师和学生都需要维护外键,修改老师会修改一次外键(造成两个update),修改学生也会修改一次外键(造成两个update)
>>解决方式:
在一对多中:
让其中一方放弃维护外键 ---> 在set标签上使用 inverse="true" 属性 表示放弃维护
让 一 的那一方放弃维护外键
>>比拟:
就好像 所有学生都认识一个老师 但老师不一定认识所有学生(老师放弃了维护学生集合外键)
8.五种查询方式
8.1 对象导航查询
用session查到一个对象后,再用该对象的get方法获取到该对象中的对象(属性)
Student stu = session.get(Student.class, "1");
Teacher teacher = stu.getTeacher;
8.2 OID查询
根据id查询记录
(1)调用session里面的get方法实现
session.get(Student.class, "1");
8.3 HQL查询(Query)
hibernate query language 使用Query对象来进行查询操作
8.4 QBC查询(Criteria)
(1)创建Criteria对象
(2)调用方法得到结果
8.5 本地SQL查询(SqlQuery)
用本地的数据库来进行查询
(1)创建SqlQuery对象
(2)调用方法得到结果
9.离线查询(DetachedCriteria)
使用原因:多条件查询,查询或与关系不明确时 等 查询的条件不明确,要用户传递查询条件时需要用到。
使用方法:使用DetachedCriteria来构造查询条件
(1)创建对象DeatchedCriteria criteria = DetachedCriteria.forclass(Class);
(2)增加条件 criteria.add() / criteria.addOrder() /...
(3)执行查询
10.迫切 内(左外) 连接 fetch 返回对象不是数组(Query)
有无迫切的区别:迫切返回的list里面每个部分是对象,没有迫切返回的list里面是数组
主要用法就是在hql中加入关键字fetch + 子对象(比如学生类里面的老师)
from Customer c inner join fetch c.setLinkMan
from Customer c left outer join fetch c.setLinkMan
但是没有迫切右外连接?
11.hibernate检索策略(立即查询和延迟查询(又分两个)-->优化)
(1)立即查询:根据id查询,调用get方法,一调用get方法马上发送语句查询数据库
(2)延迟查询:根据id查询,还有load方法,调用load方法不会马上发送语句查询数据,
只有需要get对象里面的值时候才会发送语句查询数据库
类级别延迟:根据id查询返回实体类对象,调用load方法不会马上发送语句
关联级别延迟:查询某个客户,再查询这个客户的所有联系人,查询客户的所有联系人的过程是否需要延迟,这个过程称为关联级别延迟
在映射文件中进行配置实现
(1)根据客户得到所有的联系人,在客户映射文件中配置
2 在set标签上使用属性
(1)fetch:值select(默认)
(2)lazy:值
- true:延迟(默认)
- false:不延迟
- extra:极其延迟
12.批量抓取
查询所有的学生,以及学生下所对应的老师,用两个FOR循环会产生大量的SQL
在老师的映射文件中,set标签配置
batch-size值,值越大发送语句越少