文章目录
最近学习了一点hibernate框架的知识,打算记录下来,如果存在什么不足希望多指教
Hibernate
一、Hibernate框架的搭建
1.导包
2.创建数据库,准备表
3.书写orm元数据(对象与表的映射配置文件)
4.书写主配置文件,在src下创建一个文件hibernate.cfg.xml(固定)
(一)orm 元数据的配置
<hibernate-mapping></hibernate-mapping>
:配置表与实体对象的关系
package属性:填写一个包名.作用:在元素内部凡是需要书写完整类名的属性,可以直接写简答类名了.
<class>
:配置实体与表的对应关系
属性:name:完整类名 table:数据库表名
<id>
:配置主键映射的属性 name:主键的对应属性名 column(可选):填写表中的主键列名,默认值:列名会默认使用属性名 type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.每个类型有三种填法: java类型|hibernate类型|数据库类型 not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
<generator>
:放在id内,主键生成策略
<property>
:除id之外的普通属性映射,name:属性名 column:列名 type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型.每个类型有三种填法: java类型|hibernate类型|数据库类型 not-null(可选):配置该属性(列)是否不能为空. 默认值:false
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度
二、Hibernate主配置文件.
必选属性配置(5个):数据库驱动<property name="hibernate.connection.driver_class"></property>.
数据库url<property name="hibernate.connection.url"></property>
数据库连接用户名<property name="hibernate.connection.username"></property>
数据库连接密码<property name="hibernate.connection.password"></property>
数据库方言(不同的数据库中,sql语法略有区别. 指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成.)<property name="hibernate.dialect"></property>
可选属性配置(3个):
<property name="hibernate.show_sql"></property>
将hibernate生成的sql语句打印到控制台
<property name="hibernate.format_sql"></property>
将hibernate生成的sql语句格式化
<property name="hibernate.hbm2ddl.auto"></property>
自动导出表结构,自动建表
属性:
- create:自动建表,每次框架运行都会创建新的表,以前表将会被覆盖,表数据会丢失(开发环境中测试使用)
- create-drop:自动建表,每次框架运行结束都会将所有的表删除
- update:自动生成表,如果已经存在不会再生成
- validate:校验,不自动生成表,每次启动会校验数据库中是否正确
元数据引入配置:路径书写:填写src下的路径
<mapping resource=””>
三、Hibernate API:
(一)Configuration:配置加载类,用于加载主配置,orm元数据
-
configure:空参加载方法,加载src下的hibernate.cfg.xml文件
-
addResource(resourceName)
-
addClass(pesistentClass):读取指定orm元数据,如果主配置文件已经引入映射配置,不需要主动加载
-
buildSessionFactory:根据配置信息,创建SessionFactory对象
-
SessionFactory:用于创建操作数据库核心对象session对象的工厂,sessionFactory负责保存和使用所有配置信息,消耗内存资源大,属于线程安全的对象设计,要保证在web项目中,只创建一个sessionFactory对象,内部维护连接池。
-
openSession:打开session
-
getCurrentSession:获得一个与线程绑定的session,session表达hibernate框架与数据库之间的连接,类似于connection对象,还可以完成对数据库的增删改查操作,session是hibernate操作数据库的核心对象
(二)Transaction:
- session.getTransaction:获得操作事务的对象
- session.beginTransaction:获得操作事务的对象并开启
- session.save:保存
- session.get:查询
- session.update:修改
- session.delete:删除
- commit:提交事务
- rollback:回滚事务
四、hibernate中的实体规则
1.持久化类需要提供无参构造
2.成员变量私有,提供get/set方法访问(需提供属性)
3.持久化类中的属性,应尽量使用包装类型
4.持久化类需要提供oid,与数据库的主键列对应,hibernate中通过持久化类的oid的属性区分是否为同一个对象
5.不要用final 修饰class,hibernate使用cgf代理生成代理对象,代理对象是继承被代理对象,如果被final 修饰,将无法生成代理
五、主键
主键的类型分为自然主键和代理主键
- 自然主键:表的业务列中,有某业务列符合,必须有,并且不重复的特征时,该列可以作为主键使用
- 代理主键(常用):表的业务列中,没有某业务列符合,必须有,并且不重复的特征时,创建一个没有意义的列作为主键
主键生成策略:id下的generator,每条记录录入时,主键的生成规则(7个)
-
identity:主键自增,适用short,int,long类型的主键,由数据库来维护主键值,录入时不需要指定主键,适用于有自动增强机智的数据库(Mysql,mssql)
-
increment:主键自增,适用short,int,long类型的主键,在单线程程序中使用,由hibernate来维护,每次插入前会先查询表中id最大值,+1做为新主键,开发时不常用,有线程安全问题,多个同时插入可能会产生数据丢失
-
sequence:适用short,int,long类型的主键,采用的是序列的方式,oracle中的主键生成策略
-
hilo:高低位算法,主键自增,由hibernate来维护,开发时不使用
-
native:hilo+sequence+identity,自动三选一策略
-
uuid:产生随机字符串,作为主键,主键类型必须为string类型
- assigned:自然主键生成策略,hibernate不会管理主键值,由开发人员自己录入
六、hibernate中的对象状态
hibernate中的对象状态,对象分为三种状态:
-
瞬时状态:没有id,没有与session关联,没有在session缓存中
-
持久化状态:有id,与session有关联,持久化状态对象的任何变化都会自动同步到数据库,在session缓存中
-
游离|托管状态:有id,没有与session关联,没有在session缓存中
七、hibernate中的批量查询
(一)HQL查询(多表查询,但不复杂时使用):Hibernate Query Language,Hibernate独家查询语言,属于面向对象的查询语言
-
基本查询:
1.书写hql语句 String hql = “from Customer “
2.根据hql语句创建查询对象
3.根据查询对象获得结果 -
条件查询:String hql = “from Customer where cust_id = ?/:cust_id”
-
分页查询:Query query = createQuery(hql)
query.setFirstResult(1);
query.setMaxResult(1);
hql语句中,不可能出现任何数据库相关的信息
>---gt >= ----ge < ---- lt <= ---- le == ---- eq != ---- ne in ---- in between and ----- between like ----like is not null ---- isNotNull is null ---isNull
or ---- or and ---- and
(二)Criteria查询(单表查询):Hibernat自创的无语句面向对象查询
1.基本查询:Criteria criteria session.createCriteria(Customer.class);List list = criteria.list()
2.条件查询:criteria.add()
3.分页查询:criteria.setFirstResult(),criteria.setMaxResult()
八、原生SQL查询(复杂的业务查询):
1.基本查询:session.createSQLQuery(),将结果集封装到哪个对象上,query.addEntity(Customer.class)
2.条件查询
3.分页查询
九、HQL的多表查询
-
内连接: 查询出的结果把关联的两个对象分别返回,放到数组中
-
迫切内连接:查询出的结果把其中一个对象放到另一个对象中,帮我们进行封装,返回一个对象
-
外连接
十、查询优化
(一)类级别查询:
- 懒加载(延迟加载):仅仅获得没有使用,不会查询 session.get方法:立即加载,执行方法时立即发送sql语句查询结果
session.load方法(延迟加载):是在执行时,不发送任何sql语句,返回一个对象,使用该对象的时候,才执行查询,是否对类进行延迟加载,可以通过在hibernate.cfg.xml的class元素上配置lazy属性来控制,true,加载时,不查询,使用时才查询,false,加载时立即查询(返回一个代理对象,这个代理对象具有根据当前session查询数据库的功能,当你使用这个对象的时候,如果发现对象中的属性还没初始化,就会调用代理中的增强功能来查询数据库来把数据加载出来),使用懒加载时要确保,调用属性加载数据时,session还是打开的,不然会抛出异常
关联级别查询:在对象.hbm.xml下的set元素配置lazy和fetch属性 - 延迟加载:lazy属性决定是否延迟加载 true(默认值):延迟加载 false:立即加载
extra:极其懒惰,与懒加载效果基本一致,如果只获得集合的size,只查询集合的size
proxy:取决于另一端的上的lazy的值 抓取策略:fetch属性决定加载策略,使用什么类型的sql语句加载集合类型
select(默认值): 单表查询加载 join:使用多表查询加载集合,此时lazy属性失效,无论lazy是啥都是立即加载
subselect:使用子查询加载集合
为了提高效率,fetch的选择应该选择select,lazy的取值应选择true,全部使用默认值,但是这会出现一个问题,一般session都是在service层关闭,而使用懒加载是在web层使用,此时session已经关闭
no-session问题解决:扩大session的作用范围,利用filter在filter打开session,事务,待servlet,service,dao,jsp执行过后关闭session,事务 - 批量抓取:一的一方在对象.hbm.xml下的set元素配置batch-size属性,多的一方在对象.hbm.xml下的class元素上配置batch-size属性
十一、Hibernate的一级缓存
Hibernate的一级缓存,称为是Session级别的缓存,一级缓存生命周期与Session一致(一级缓存是由Session中的一系列Java集合构成)。一级缓存是自带的不可卸载的。Hibernate的二级缓存是SessionFactory级别的缓存,需要配置的缓存。
十二、cascade跟inverse
一对多关系中双方都维护关系时会发送多余的SQL语句,造成数据库资源浪费,因此要采用inverse属性放弃一的一方的维护关系
cascade跟inverse的区别:cascade是维护关联关系,一个对象存入数据库,关联的对象也会存入数据库,但是外键为空,外键是由inverse来维护的