Hibernate -----总结
一、在使用Hibernate的时候
首先我们要导入Hibernate类库,导入Hibernate压缩包中lib文件中required中的包
其后我们要进行对数据的操作,所以还需要一个数据库驱动包,例如mysqlconnector....,
二、准备工作
1)首先我们要建立好实体类和映射文件(通过注解也可以实现,在后面会讲到)
在实体类的同目录下创建映射文件(类名.hbm.xml),导入dtd约束(hibernate-mapping-3.0dtd)
1 2 3 5 67 8 25 26 279 11 12 1310 14 15 16 17 18 19 22 23 2420 21
2)准备主配置文件
在src目录下,新建hibernate.cfg.xml文件,导入dtd约束(在hibernate-configuration-3.3.dtd)中
org.hibernate.dialect.MySQL55Dialect com.mysql.jdbc.Driver root 123456 jdbc:mysql://localhost:3306/hibernateStudy?characterEncoding=UTF-8 update true true thread true org.hibernate.cache.ehcache.EhCacheRegionFactory true
3、配置解释
hibernate-mapping: package-在下面的配置文件中的类就默认为这个包下的类 不用每次都写包名在写类名
class属性:映射表与类的对应 name:类名 table:该类对应数据库中建表的名字
id属性:id代表主键(映射主键)
name:类中主键属性名字
column:主键所在列的名字
length:主键字段的长度,默认为数据库对应数据类型的最大长度
type:当前列的数据类型,默认自动检测 (可以不写,我就不写,写还容易写错,还不如让他默认找)
generator属性:代表的是主键生成策略
代理主键:increment 先查询表中的主键最大值,加1作为新的主键(不建议使用,效率低)
identity:主键自增 只能用于支持主键自增的数据库 mysql支持 oracle不支持
sequence:使用数据库中的序列 每次取得时候会自动增加 ORacle中所使用的
hilo:hibernate自己用高低算法完成主键自增
uuid:生成随机字符作为主键 默认(32位)
native(常用):自动根据数据库的三选一(identity sequence hilo)
自然主键:
assigned:hibernate不生成主键,由开发人员自己设置主键值
property属性:(映射的普通列)
name属性:类中属性名
column:表中字段名
length 和 type 同上面 length type
主配置文件中:
自动建表 :(hibernate.hbm2ddl.auto)
create:自动建表,每次启动hibernate的时候都还自动创建表,如果表存在,那就删除之后在创建
create-drop:自动建表,每次运行完成后再将表删除
update:自动建表,如果有表,就不在重新建表,如果配置改变,自动更改表的结构
validate:不会自动创建表的结构,只负责在启动的时候检验表的结构,如果有问题就会抛出异常
API详解
configuration:config 读取配置文件
buildSessionFactory 创建sessionFactory
Configuration conf = new Configuration().config;
SessionFactory sf = conf.buildSessionFactory();
SessionFactory:
根据配置信息创建session对象
1、SessionFactory创建需要消耗较多的内存资源
2、SessionFactory是线程安全的设计。
在一个web项目中确保只有一个SessionFactory存在
获得session:
Session session = sf.openSession(); //获得一个新的session 每个session都不同
Session session = sf.getCurrentSession();//获得与线程绑定的session,需要在主配置文件中配置,不需要手动关闭session,线程安全的。
(<property name="hibernate.current_session_context_class">thread</property>)
Session:
hibernate中操作数据的核心对象
1、操作增删改查
2、获得事务操作对象
beginTransaction | getTransaction 获得事务对象,第一个还具有开启事务的功能
get|load oid操作 根据给定标识和实体类返回持久化对象的实例
save 插入
delete 删除
update 修改
saveOrupdate 如果表中没有要操作的对象 那么就执行save 否则执行update
createQuery 根据给定的HQL查询条件创建一个新的Query的实例
createCriteria 根据给定的实体名称,创建一个新的Criteria实例 (过时)
createSQLQuery 根据给定的SQL查询条件创建一个新的SQLQuery实例(过时)
createNativeQuery 就是根据原生的sql语句来创建一个query实例
注意的地方: get 是立即加载
load 是延迟加载 调用的时候不会发送sql语句,返回一个代理对象,使用对象的时候才执行查询语句
Transaction(事务)
用于操作事务的对象
try{
Transaction transaction = session.beginTransaction(); //开启事务
transaction.commit(); //事务提交
}catch(Exception e){
transaction.rollback(); //事务回滚 当出现异常的时候
}
创建实体对象的规则:
1、public的空参构造方法
2、私有化属性 public的get/set方法
3、提供oid,映射主键字段
4、标识属性尽量使用基本数据类型的包装类 例如: 能用Integer尽量别用int 能用Long尽量别用long
5、类不能被final修饰
Hibernate中对象的三种状态
1、瞬时态 没有id 没关联
2、持久态 有id 有关联
3、游离态 有id 无关联
持久化状态:持久化状态对象会在事务提交的时候持久化到数据库,我们需要将对象持久化到数据库,就需要把对象转换为持久化状态。(注意在对象已经是持久态的情况下,对对象重新赋值,在事务提交之后会生成一条update的sql语句,来更新数据库中的对象的值让其与当前对象保持一致) 不用你自己去调用session.update()方法,没有用,只有在事务提交后才会生成一条sql语句
还有:当session进行 get、load方法的时候,如果数据库中有这个对象,则表示这个对象已经是持久化状态,当你对他进行重新赋值的时候,(他会将数据库中的值和session中的值进行比较)在事务提交的时候仍然会向数据库发送一条update语句。来更新对象
他就是拿数据库中的值和session中保存的对象进行比较 如果在事务提交之前你进行了session.clear()的时候,session中不存在该对象了,事务提交的时候他也不会去执行update
User u = new User(); //游离态
u.setId(3);
session.update(u); //完成update后也会变成持久化状态
u.setId(5); //当你设置一个持久化对象的主键值的时候就会抛出异常
transaction.commit();
一个session中不能存在对一个持久化对象的双重Copy
例如:User user1 = (User)session.get(User.class,1); user1是持久态度
User user2 = new User(); user2是瞬时态
user2.setId(1);
session.saveOrupdate(user2) ; //此时user2也会变成持久态度,但是session中不能存储同样的对象两份会抛出异常。
解决方法: 用session.merge(u2); //该方法的作用就是先判断是否包含同一对象,如果包含则合并 (基本不用)
二、缓存
一级缓存:也称为session缓存,属于线程级别缓存,该缓存的本质就是一个集合,该集合被放置到了session对象中,所以也称为session缓存,因为session是线程级别的,所以该缓存也称为线程级别缓存。
缓存的作用:提高查询,修改的效率
查询:根据id查询对象
ResultSet会被封装成对象,放入缓存以及返回程序。如果缓存中存在要查找的id,返回缓存中的对象。
修改:根据id查询对象
ResultSet会被封装成对象,一式两份,分别放入session缓存以及缓存快照中
事务在提交的时候,会比对session缓存中的以及快照中的对象是否发生变化。如果发生变化执行修改
三、Hibernate中的事务管理
设置事务的隔离级别:
有4种等级 1 2 4 8
Read uncommitted(读未提交) 最低级别(脏读、虚读(幻读)、不可重复读都可能发生)
Read committed (读已提交) 可以避免脏读的发生,虚读和不可重复读可能发生
Repeatable read (可重复读) 可以避免脏读 和不可重复读的发生
Serializable(串行化) 全都可以避免
事务有service(逻辑层)管理,确保service层和dao层使用的是同一个连接 session(Connection)
可以用getCurrentSession从ThradLocal中获得与线程绑定的session
getCuurentSession配置之后才能使用
<property name="hibernate.current_session_context_class">thread</property>
getCurrentSession获得的session对象会在事务提交的时候自动关闭,不用手动关闭。
四、一对多 多对一 关系
ORM:对象关系映射
o:一的一方使用集合,多的一方直接引用一的属性
r:多的一方使用外键引用一的一方
m:一对多关系映射 多对一关系映射
一般我们用的时候都用set集合 list集合还得添加一个index字段
一对多的关系:
<set name="集合属性名">
<key column="外键名"></key>
<one-to-many class="多的一方的类名"/>
</set>
多对一的关系:
<many-to-one name="引用一方的属性名" column="外键名字" class="一的一方的类名"/>
五、级联操作
Cascade属性:级联操作
none:默认值 不级联
save-update:级联保存或者更新
delete:级联删除
all:save-udate delete
其实级联的作用就是减少书写代码, 删除不建议使用 风险较大
inverse:是否维护关系
true:放弃
false:维护(默认)
一对多中可以使用inverse属性放弃维护关系,多对一中不能放弃维护关系
<set name="Order" inverse="true">
<key column="oid"/>
<one-to-many class="orderItem"/>
</set>
为了避免维护关系SQL打印冗余,可以在一的一方放弃维护。配置后,表达关系只能通过多的一方来维护
六、多对多
ORM:
o:使用第三张表,该表至少有两列,两列都是外键
r:两方都用集合来表达引用多个对方
m:多对多映射文件
七、Hibernate中的查询
a.根据oid进行查询
b.对象属性导航
c.HQL查询
d.Criteria查询
e.原生SQL查询
1、HQL: hibernate查询语言 只在hibernate使用
基础查询:String hql=“select o from Order o”;
="from Order"
Query query = session.createQuery(hql);
List<Order> list = query.list();
投影查询:
查询一个属性:
String hql="select o.money from Order o";
Query query = session.createQuery(hql);
List<String> list = query.list();
查询两个属性:
String hql="select o.money,o.id from Order o";
Query query = session.createQuery(hql);
List<Object[]> list = query.list();
查询多个对象,并封装到对象中
String hql="select new Order(o.id,o.money) from Order o";
Query query = session.createQuery(hql);
List<Order> list = query.list();
//要在实体类中的构造方法中写 id 和 money
条件查询:
问号?占位符
String hql="from Order o where o.money=?";
Query query = session.createQuery(hql);
query.setParameter(0,"220"); //hql 从0开始 原始sql从1开始
List<Order> list = query.list();
命名占位符 :low (冒号后面加变量名字)
String hql=" from Order o where o.id between :low and :high"
Query query = session.createQuery(hql);
query.setParameter(0,"20"); //hql 从0开始 原始sql从1开始
queey.setParameter(1,"89");
List<Order> list = query.list();
分页查询:
hql不支持 insert limit *
limit可以用 setFirstResult() setMaxResult()
String hql=" from Order"
Query query = session.createQuery(hql);
query.setFirstResult(0); //从几开始
query.setMaxResult(4); //查询几条数据
List<Order> list = query.list();
排序:
desc 降序 asc 升序
String hql=“from Order o order by o.id desc ”;
.....
聚合函数查询:Count Max Sum Avg
String hql="select count(Order) from Order";
、。。。。。
Long count = (Long) query.uniqueResult();
count 返回的值是Long类型
多表查询:
内连接: 两个表 一个Order 一个 OrderItem
hql=“select o.id,o.money,od.id from Order o inner join on OrderItem od
where o.id==od.id”
左连接:select o.id,o.money,od.id from Order o left join OrderItem od where
o.id==od.id"
右连接:left 换成right 就好了
HQL适用于单表和简单多表 如果复杂的你就用 原生的sql写吧
Criteria 查询 (现在已经过时)
hibernate 框架中独有的查询方式
Criteria 无语句面向对象查询
Criteria 一般用于单表查询
1、基础查询:
创建查询对象 Criteria c = session.criteria(Order.class);
List<Order> list = c.list();
2、条件查询:
Criteria c = session.criteria(Order.class);
c.add(Restrictions.and(Restrictions.between("id",2,5),Restrictions.like("name","李%")));
查询~~·
3、分页查询:
c.setFirstResult(2);
c.setMaxResult(21);
4、排序查询
c.addOrder(Order.asc("age")); //升序
List<Order> list = c.list();
5、聚合查询
c.setProjection(Projections.Count("id"));
Long count = (Long)c.uniqueResult();
离线Criteria查询对象 不需要session就可以直接创建
DetachedCriteria dc =DetachedCriteria.forClass(Order.class);
//设置条件
dc.add(Restrictions.and(Restrictions.between("id",2,5),Restrictions.like("name","李%")));
//将离线查询与session相关联
Criteria c = dc.getExecutableCriteria(session);
//执行操作
List<Order> order = c.list();
适合单表
查询策略:
类级别查询策略:
lazy属性:是否懒加载|延迟加载
true: 默认懒加载 用load
false:立即加载
:返回对象的初始化操作一定要咋session关闭之前完成 否则就会跑出 no-session 异常
Hibernate注解式开发
使用了注解就不用写映射配置文件
Hibernate的注解是基于JPA(java持久化api)---spring Data JPA
映射配置文件:
类--表 主键 属性---字段 常用的注解: 1、修饰类: 1、@Entity 标记实体 也可以指明表名 2、@Table 设置对应的表的信息,必须有 常用属性: name 表名 2、修饰属性:1、@Column 设置字段信息,比如字段名称、长度、约束等
常用属性: name 字段名称 length 字段长度 unique 是否唯一 2、@Basic 标记属性是字段 默认有3、@Transient 标记该属性不是字段
4、@Temporal 设置日期的类型
常用属性: value 取值说明: TemporalType.DATE 日期 TemporalType.Time 时间 TemporalType.TIMESTAMP 日期+时间5、@Lob 设置大数据的类型 对应的blob或clob
3、主键:
1、@Id 主键 2、@GeneratedValue 自增策略 常用属性: 1、strategy 使用自带的增长机制 GenerationType 2、generator 使用自定义的增长策略@GenericGenerator(name = "assigned",strategy = "七中主键增长策略")//定义增长策略
@GeneratedValue(generator = "assigned")//使用自定义的增长策略 4、多表关系 1、@OneToOne 一对一 常用属性: 1、targetEntity 目标类的Class对象 2、mappedBy 设置关联属性 3、fetch 设置加载类型 --lazy 取值: FetchType.EAGER 立即加载 FetchType.LAZY 懒加载 4、cascade 设置级联关系 取值: CascadeType.PERSIST 级联保存 CascadeType.ALL 所有 CascadeType.MERGE 修改 CascadeType.REMOVE 删除 CascadeType.REFRESH 刷新 CascadeType.DETACH 不使用级联 none 2、@JoinColumn 设置外键字段 ,关联字段 常用属性: name 字段名称 3、@Fetch 标记抓取策略 多表关系中,如何关联查询相关表 取值: FetchMode.JOIN 使用连接查询 FetchMode.SELECT 使用独立好像 4、@ManyToOne---一般是拥有外键 标记多对一 常用属性: targetEntity cascade 5、@OneToMany 一对多 常用属性: mappedBy 设置关联属性 6、@ManyToMany 多对多--隐式 常用属性: targetEntity 7、@JoinTable 设置关联表 常用属性: name 关联表表名 joinColumns 数组 标记当前表在关联表中的外键名称 使用的@JoinColumn inverseJoinColumns 数组 标记另一个表在关联表中的外键名称 使用的@JoinColumn
基于注解的映射配置:
<mapping class="包名.类名">