hibernate 自动建表的字符编码问题
在数据库连接url中加入?useUnicode=true&characterEncoding=utf8
或者重写下MySQL5InnoDBDialect,在配置文件中将方言指定成重写后的方言
package com.yrj.dialect;
import org.hibernate.dialect.MySQLDialect;
public class CustomDialectUTF8 extends MySQL5InnoDBDialect{
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
}
然后配置修改
<property name="hibernate.dialect">com.yrj.dialect.CustomDialectUTF8 </property>
hibernate是利用对象标识符OID来区分对象
比如 获取对象时候,已经获取了id为1和2的对象,此时再去获取1的对象时候,会去session缓存中查看是否已经存在该对象,如果有则直接读取,不再去数据库查询。
junit中有类加载之前、测试方法前、测试方法、测试方法后、类加载之后方法排序
级联保存更新
在多的一端对象配置文件里加many-to-one
<set name = "xx" table="t_xx">
<key column="外键,所属类的id,任意名字"></key>
<element column="xx集合值列名" type="string"/>
</set>
2.List xx集合 有序可重复
在类的hbm.xml中,属性里面有(将该list作为一张表看待)
<list name = "xx" table="t_xx">
<key column="外键,所属类的id,任意名字"></key>
<list-index column=" list_index" />
<element column="xx集合值列名" type="string"/>
</list>
3.Bag xx集合(是在hibernate表里无序可重复) 写在类中属性也是List集合
在类的hbm.xml中,属性里面有(将该list作为一张表看待,有主键)
<idbag name = "xx" table="t_xx">
<collection-id type="long" column="imageId">
<generator class="increment" />
</collection-id>
<key column="外键,所属类的id,任意名字"></key>
<element column="xx集合值列名" type="string"/>
</idbag>
4.Map
<map name = "xx" table="t_xx">
<key column="外键,所属类的id,任意名字"></key>
<map-key column="imageKey任意名" type="string"/>
<element column="xx集合值列名" type="string"/>
</map>
hibernate映射继承
1.每个继承抽象类的具体类(抽象类没有对应表)对应一个表。即是几个类继承了抽象类,但是几个类都有各自的表。
但是在有List<根类>作为属性的类中配置时候不可以加set映射多,导致获取时候只能通过该id作为外键通过hql查询来获取list再合并
hql语句:from 继承抽象类的类名 al al.一属性.id=xx
2.根类对应一个表。即是当根类是具体类,几个类继承了根类,只用编写根类的hbm.xml,编写时候除了正常属性等的配置,还要加一个 (这是在实体类也存在的属性)
并且加
…
这时候只会生成一个表。 并且在有List<根类>的属性的类中配置时候可以加set映射多,到时候获取就可以通过session.get()获取到对象再获取set的集合
3.每个类对应一个表。即是当根类是具体类,几个类继承了根类,也是只用编写根类的hbm.xml
但是编写时候除了正常属性外(这时候实体类没有2的那个xx继承类型 属性),增加
<joined-subclass name="子类类名1" table="子类表名1" >
<key column="子类表主键名称,也扮演了和根类id关联的外键角色" />
</joined-subclass>
<joined-subclass name="子类类名2" table="子类表名2" >
<key column="子类表主键名称,也扮演了和根类id关联的外键角色" />
</joined-subclass>
这时候是根类和子类都有表
第八章
一对一映射关系
①主键关联映射
比如两个实体类User和Address
编写User.hbm.xml时候,其他属性保持正常写法,并写好one-to-one 的name和class,还有cascade为all。
在Address.hbm.xml中,
配置id时候用的不是native,并且user就是Address类中的属性
<id name="id" column="addressId">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
还有
one-to-one 的name和class,constrained=“true”
②外键关联映射
编写User.hbm.xml时候,其他属性保持正常写法,并写好many-to-one 的name和class,cascade 为all,还有unique为true(保证一对一),column为addressId
编写Address.hbm.xml,正常配置属性,并对user属性用one-to-one,其中的name、class还有个property-ref的值为 User类中的address名。
多对多映射关系
①单向实现
只能通过一方获取set集合。
比如Student和Course,在Student中有Set courses(此处属性要new),那么配置文件时候,
Student.hbm.xml中除了正常的属性外,courses属性的配置为
(作为临时表”student_course” 的对应student外键)
(作为临时表的对应course的外键)
而Course.hbm.xml则正常配置(单向时候只有简单属性,无set属性)
②双向实现
两方都可以获取set集合。
此时两个类都有set属性
Student.hbm.xml和①一样
此时的Course.hbm.xml添加一样的set,不过使用的是inverse而不是cascade,代表由学生设立维护(即在set中设立的inverse对应的是哪个类就是哪个类维护)
(作为临时表”student_course” 的对应course外键)
(作为临时表的对应student的外键)
第九章 Hibernate 检索策略
1.lazy属性
延迟检索则为,相关属性使用到的时候才去查询,如放在set端,则set的属性在我们需要使用的时候才会去查库返回。
增强延迟检索则为,如果这个set属性只是需要size而已,那么和延迟检索的差别就是延迟还是会把set全部查,但是增强延迟只count出来。优化。
true (默认值) 延迟检索;set端 一对多中
false 立即检索; set端 一对多
extra 增强延迟检索; set端 一对多
proxy(默认) 延迟检索;many-to-one标签 多对一中
no-proxy 无代理延迟检索;many-to-one标签 多对一 (需要编译时字节码增强)
2.batch-size属性 set端 一对多中
批量作用
比如在查询很多个“一”(n个)的对应多集合时,
正常时候后台的语句是每个一 去找,比较麻烦
批量延迟检索:batch-size =“n”和lazy=“true”一起使用 可以只执行一条语句 n指定的是多少个“一”,即合并这些语句一条语句查完。
批量立即检索:batch-size =“n”和lazy=“false”一起使用 获取一的时候不用等使用set就已经检索出来set了,立即检索。不过size如果设置的比一的数目少,还要另外将剩下的“一” 一条条语句查询出来。
3.fetch属性 set端 一对多中
select 默认 批量时候的in 后面的集合是直接获取到的全部准确值(2条查询)
subselect 批量时候的in 后面的集合是通过子查询 (2条查询)
join 外连接 也就是左连接 在hql查全部时候无效,还是体现select的作用。但在获取单独一个时候,要和set集合关联则为一条语句left join完,而select则是先查一,再根据一的准确值查多
第十章 Hibernate的查询方式
本地SQL查询:
sql语句写好,使用的是session的createSQLQuery方法,还要.addEntity(xx.class)指明对象类,这样得到的Query,之后的list才可以在使用iterator遍历时候转为对应对象。
当sql有参数时候,如select * from t_stu where stu_name like :stuName and stu_age = :stuAge,
query得到之后,用其setString(stuName,“xx”)和setInteger(stuAge, 11)赋值参数
然后获取list,遍历。
=============
HQL查询:
1.hql语句: from 对象; 如from Student
session.createQuery(hql);即可
2.带上参数时候的hql语句:
from Student where name like :stuName and age =:stuAge
获取到Query之后,用其setString(stuName,“xx”)和setInteger(stuAge, 11)赋值参数
再query.list(),遍历
3.分页的操作
hql写好后,获取Query,使用query.setFirstResult(num),和query.setMaxResult(count)
从第num下标开始,获取count条。
4.获取单个对象
也是query设置好分页那些属性,只是setMaxResult的count为1,这就是确认只有一个对象,此时不使用query.list而是使用query.uniqueResult获取单个对象。
query.uniqueResult也是统计行数的方法。也就是count(*)
5.链式写法
有参数时候,可以直接query一次性set完,比如query.setString().setInteger().list();
==========
QBC查询方式:
Query By Critera —>hibernate提供的接口实现查询方式
具体做法是
1.
Criteria criteria = session.createCriteria(xx.Class);
criteria.list();即可普通查询全部数据。
2.带条件的查询
获取到criteria之后,
Criterion c1 = Restrictions.like(“name”,”张%”);//属性name值 像什么
Criterion c2 = Restrictions.eq(“age”,11);//int属性age值 是什么
criteria.add(c1);
criteria.add(c2);
然后获取list。
3.排序
获取到criteria之后,
设置好条件,然后设置排序
criteria.addOrder(Order.desc(“age”));
然后list
4.分页
获取criteria之后,
criteria.setFirstResult(num);
criteria.setMaxResults(count);
从第num下标开始,获取count条。和hql类似。
然后list
5.查询单个对象
和分页一样,也是criteria设置好分页那些属性,只是setMaxResult的count为1,这就是确认只有一个对象,此时不使用criteria.list而是使用criteria.uniqueResult获取单个对象。
6.链式写法
criteria.setFirstResult(num).setMaxResult(count).list();
第十一章 高级配置
1.配置数据库连接池
Hibernate的连接池不是很好,
使用这个C3P0、proxool较好。
引入jar包,lib->c3p0
在hibernate.cfg.xml文件中配置连接属性
2.配置日志框架Log4j
添加jar包
建立log4j.properties文件
级别由高到低(级别越高输出越少)
OFF/FATAL/ERROR/WARN/INFO/DEBUG/ALL
类似配置文件可以如下:
log4j.rootLogger=debug,appender1,appender2 输出等级、和多个扩展输出名字
log4j.appender.appender1=org.apache.log4j.ConsoleAppender 输出位置1
log4j.appender.appender2=org.apache.log4j.FileAppender 输出位置2
log4j.appender.appender2.File=C:/logFile.txt 输出位置2 的具体文件
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout 布局,输出内容格式
log4j.appender.appender2.layout=org.apache.log4j.TTCCLayout
3.配置二级缓存
Hibernate缓存分类:
①Session 缓存,又叫事务缓存:Hibernate内置,不能卸除
Session关闭,缓存结束。一级缓存
找到数据后存在缓存中,同个session未关闭前,再次获取对象为缓存中对象。
②SessionFactory缓存,又叫应用缓存:使用第三方插件,可插拔
session对象共享,应用关闭,缓存结束。 二级缓存
开了两个session,也就是两个事务,两个事务获取对象不同,一级缓存不能共用
配置EHCache(二级缓存)
引入jar包,在下载的框架的lib下的optional中
配置ehcache.xml文件
内存满了之后,可以允许写到硬盘上
配置hibernate.cfg.xml文件
这之后,还需要在获取的类的xx.hbm.xml中配置cache,和id、property同级。
此时就可以在两个事务中,获取同个在二级缓存中的对象。