在劫

吾生也有涯,而知也无涯 。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

什么是Hibernate框架:
1、hibernate框架应用在javaee三层结构中dao层框架
2、在dao层里面做对数据库crud操作,使用hibernate实现crud操作。hibernate底层代码就是jdbc,hibernate对jdbc进行封装,使用hibernate好处就是不需要写复杂的jdbc代码了,不需要写sql语句实现
3、hibernate开源的轻量级框架
ORM思想
hibernate使用orm思想对数据库进行crud操作
orm:object relational mapping 对象关系映射
让实体类和数据库表进行一一对应关系
让实体类首先和数据库表对应
让实体类属性和表里面字段对应
不需要直接操作数据库表而操作表对应实体类对象
搭建hibernate环境
1、导入jar包,lib目录下的required文件夹、mysql驱动、和外部日志jar包
2、创建实体类

public class User(){
	/*hibernate要求实体类要有一个属性唯一的*/
}

3、使用hibernate不需要自己手动建表,hibernate会自动建表
4、配置实体类和数据库一一对应关系(映射关系)

使用配置文件实现映射关系
1、创建XML格式的配置文件:映射配置文件名称和位置没有固定要求,一般建议在实体类所在的包里面创建,名字:实体类名称.xml
2、配置文件是xml格式,在配置文件中首先引入xml约束

<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 

3、配置映射关系

<hibernate-mapping>
	<!--配置类和表对应
		class标签
		name属性:实体类全路径
		table属性:数据库表名
	-->
	<class name="  " table="t_user">
		<!--配置实体类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="属性名" column="生成表字段名称"></property>
		<!-- ......-->
	</class>
</hibernate-mapping>

4、创建hibernate核心配置文件
(1)核心配置文件格式xml,但是核心配置文件的名称和位置固定的,位置必须在src下面,名称必须hibernate.cfg.xml
(2)引入dtd约束

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

(3)hibernate操作过程中,只会加载核心配置文件,其他配置文件不会加载

<hibernate-configuration>
	<session-factory>
		<!--配置数据库信息-->
		       <!-- property 元素用于配置Hibernate中的属性
            键:值 
          -->
        <!-- hibernate.connection.driver_class : 连接数据库的驱动  -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- hibernate.connection.username : 连接数据库的用户名 -->
        <property name="hibernate.connection.username">root</property>
        <!-- hibernate.connection.password : 连接数据库的密码 -->
        <property name="hibernate.connection.password">123</property>
        <!-- hibernate.connection.url : 连接数据库的地址,路径 -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedemo</property>
		<!--配置hibernate信息,这部分是可选的-->
		 <!-- show_sql: 操作数据库时,会 向控制台打印sql语句 -->
        <property name="show_sql">true</property>
        <!-- format_sql: 打印sql语句前,会将sql语句先格式化  -->
        <property name="format_sql">true</property>
        <!-- hbm2ddl.auto: 生成表结构的策略配置
             update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构. 
                     如果存在表结构,并且表结构与实体一致,那么不做修改
                     如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
             create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
             create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
             validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
          -->
        <property name="hbm2ddl.auto">update</property>
        <!-- 数据库方言配置 
         org.hibernate.dialect.MySQLDialect (选择最短的)
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- hibernate.connection.autocommit: 事务自动提交  -->
        <property name="hibernate.connection.autocommit">true</property>
        <!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
        <property name="hibernate.current_session_context_class">thread</property>
		<!--把映射文件放到核心配置文件中-->
		<mapping resource="com/it/a_hello/User.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

实现添加操作
1、加载hibernate核心配置文件

Configuration sfg = new Configuration();
cfg.configure();

2、创建SessionFactory对象

SessionFactory sf = sfg.buildSessionFactory();

3、使用SessionFactory创建session对象

Session s = sessionFactory.openSession();

4、开启事物

Transation tx = s.beginTransation();

5、写具有逻辑curd操作

User user = new User();
user.setUsername();
user.setUserage();
user.setUseradd();
//调用session的方法实现添加
s.save(user);

6、提交事物

tx.commit();

7、关闭资源

session.close();
sessionFactory.close();

Hibernate配置文件详解
映射配置文件
1、名称和位置没有固定要求
2、映射问价那种,标签name属性值写实体类相关内容:class标签name属性值实体类全路径,id标签和property标签name属性值实体类属性名称
3、id标签和property,column属性可以省略,省略默认的值和name的值一样
4、property标签type属性,设置生成表字段的类型,自动生成对应类型
核心配置文件
1、核心配置写位置要求
2、数据库部分必须的,hibernate部分可选,映射文件必须的
3、位置.src下,文件名hibernate.cfg.xml
hibernate核心api
Configuration
1、到src下面找到名称hibernate.cfg.xml文件,并加载
SessionFactory
Session
Transation
实体类的编写
1、实体类里的属性是私有的
2、私有属性要使用公开的get和set方法
3、要求实体类有属性作为唯一值(一般用id值)
4、实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装类。
Hibernate主键生成策略:
1、要求实体类有一个属性作为唯一值,对应表主键,主键可以有不同生成策略
2、主键生成策略有很多的值
3、在class属性里面由值

native:根据使用的数据库选择哪个值
uuid:之前web阶段写代码生成uuid,hebernate会自动帮我生成uuid值
使用uuid生成策略,实体类id属性必须是字符串类型

实体类操作
1、调用session的save方法实现添加
2、根据id查询

//调用session里面的get方法实现
//调用工具类得到sessionFactory
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
//获取session
Session session = sessionFactory.openSession();
//开启事物
Transaction tx = session.beginTransaction();
//根据id查询
User user = session.get(实体类的class, id的值);
//提交事物
tx.commit();
//关闭
session.close();
sessionFactory.close();

修改操作

1、先根据id查找值
//调用session里面的get方法实现
//调用工具类得到sessionFactory
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
//获取session
Session session = sessionFactory.openSession();
//开启事物
Transaction tx = session.beginTransaction();
//修改操作
//先根据id查询
User user = session.get(实体类的class, id的值);
//向返回的的user对象里面修改值
user.setUsername();
//调用session的update方法修改
session.update(user);
//提交事物
tx.commit();
//关闭
session.close();
sessionFactory.close();

删除操作

1、先根据id查找值
//调用session里面的get方法实现
//调用工具类得到sessionFactory
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
//获取session
Session session = sessionFactory.openSession();
//开启事物
Transaction tx = session.beginTransaction();
//修改操作
//先根据id查询
User user = session.get(实体类的class, id的值);
//调用session的delete删除
---------------
//方法一:根据id删除
session.delete(user);
//方法二:
User user = new User();
user.setUid(3);
session.delete(user);
-------------------
//提交事物
tx.commit();
//关闭
session.close();
sessionFactory.close();

实体类状态:
1、瞬时态:对象没有id值,对象与session没有关联
2、持久态:对象有id值,对象与session有关联
3、托管态:对象有id值,但是与session没有关联
实体类对象的方法:
saveOrUpdate方法:实现添加、修改。实体类对象是瞬时态,做添加操作;托管态,做修改操作;持久态,做修改操作
Hibernate的一级缓存:
数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很高。把数据存到内存中,不需要使用流方式,可以直接读取内存中的数据,提高读取效率。
Hibernate框架提供了很多优化方式,hibernate缓存就是一个优化方式
hibernate缓存特点:
1、hibernate的一级缓存

1、hibernate的一级缓存默认是打开的
2、hibernate的一级缓存使用范围,是session范围,从session创建d到session关闭范围
3、hibernate的一级缓存中,存储数据必须是持久态数据

2、hibernate的二级缓存

目前已经不使用了,替代技术:redis
二级范围默认不是打开的,需要打开
使用范围是sessionFactory范围

hibernate事务操作
什么是事务?
事务特性
不考虑隔离性产生问题:
1、脏读
2、不可重复读
3、虚读
事务隔离级别:mysql默认隔离级别:repeatable read
Hibernate事务代码规范写法:

代码结构:
SessionFactory sessionFactory = null;
Session session = null;
Transation tx = null;
try{
	sessionFactory = HibernateUtils.getSessionFactory();
	session = sessionFactory.openSession();
	//开启事务
	tx = session.beginTransation();
	//增删改操作
	//...
	//提交事务
	tx.commit();
}catch(){
	//回滚事务
	tx.rollback();
}finally{
	//关闭
}

Hibernate绑定session
1、session类似jdbc的connection
2、帮实现与本地线程绑定session
3、获取与本地线程session

1、在hibernate核心配置文件中配置
<property name="hibernate.current_session_context_class">thread</property>
2、调用sessionFactory中的方法得到
sessionFactory.getCurrentSession();

得到与本地线程绑定的session
session = HibernateUtils.getSessionobject();
获取与本地线程绑定session的时候,关闭session报错,这个时候不需要手动关闭

查询所有
Query对象

使用query对象,不需要写sql语句,但是写hql语句(hibernate query language Hibernate提供查询语句,这个hql语句和普通sql语句很相似)
使用普通sql操作表和表字段,hql操作的是实体类和属性
查询所有hql语句:form 实体类名称
query对象使用:
1、创建Query对象
Query query = session.createQuery("from 实体类名");
2、调用query对象里面的方法得到结果
List<实体类名> list = query.list();

Criteria对象

使用这个对象查询操作,这个对象不需要写语句
实现过程:
1、创建Criteria对象
Criteria c = session.createCriteria(实体类.class);
2、调用方法得到结果
List<...> list = c.list();

SQLQuery对象

使用hibernate也能调用底层sql实现
SQLQuery sq = session.createSQLQuery("普通sql语句");
//默认里面每部分数组结构
List<Object[]> list = sq.list();
//上面这种形式每部分是数组,现在想返回每部分是对象
//返回每部分是对象形式,步骤如下:
sq.addEntity(实体类名.class);
List<实体类名> list = sq.list();

多表操作
表与表之间的关系
1、一对多

一对多映射配置
	第一步:创建两个实体类(客户、联系人)
	第二步:让这两个实体类之间互相表示
			1、在客户实体类里面表示多个联系人 ,hibernate表示一个客户有多个联系人要求使用集合表示多的数据,使用set集合
			2、在联系人实体类里面表示所属客户
	第三步:配置映射关系
			1、一般一个实体类对应一个映射文件
			客户配置:
			联系人配置:
			2、把映射基本的配置完成
			3、在映射文件中,配置一对多关系
				在客户的映射文件中,表示所有联系人
				<!--使用set属性表示所有联系人,name属性写实体类里面表示联系人set集合的名称-->
				<set name="set集合名">
					<!--一对多建表,有外键,hibernate机制,双向维护外键,在一和多那一方都配置外键-->
					<key column="外键名"></key>
					<one-to-many class="联系人实体类完整路径"/>
				</set>
				联系人映射文件中,表示所属客户
				<many-to-one name="客户实体类名称" class="客户实体类全路径" colum="外键,和客户配置中key值一致"></many-to-one>
	第四步:创建核心配置文件,把创建的配置文件引入到核心配置文件中

----------------------------------------------------------------------------------------------------------------------------------
一对多级联操作
级联保存
	添加一个客户,为这个客户添加多个联系人
	方式一:
	1、创建客户和联系人对象
	2、创建对象和联系人对象关系,把客户放联系人里面,把联系人放客户中
	3、保存到数据库 session的save方法
	方式二:
	一般根据客户添加联系人
	1、在客户映射文件进行配置
		在set标签上进行配置,cascade属性代表级联保存
		<set name="" cascade="save-update">
	2、创建客户和联系人对象,只需要把联系人放到客户里面,最后只需要保存客户就可以
级联删除
	删除某一个客户,这个客户里面多有联系人删除	
	删除某个客户,把客户里面所有联系人删除
	1、在客户的映射文件set标签,进行配置
	<set name="" cascade="delete">
		如果级联保存的时候已经进行了配置,这个时候有多个值,多个值之间用英文逗号隔开delete,save-update
	2、在代码中直接删除客户
		根据id查询对象,根据session的delete删除
一对多修改操作
	1、根据id查询联系人,根据id查询客户
	2、设置持久态对象值,把客户放联系人里面,把联系人放客户中
inverse属性
	因为hibernate是双向维护外键,在客户和联系人里面都需要维护外键,对性能有损耗,可以让其中一方不维护外键。
	一对多里面,让其中一方放弃外键维护,让其中一的那方放弃维护
	在set标签使用inverse属性配置
	默认false代表不放弃关系维护,true放弃关系维护
	<set inverse="true">

2、多对多

多对多映射配置
	以用户和角色为例
	1、创建实体类:用户和角色
	2、让两个实体类互相表示
		用户里面表示所有角色,使用set集合
		一个角色有多个用户,使用set集合
	3、配置映射关系
		基本配置
		配置多对多关系
			在用户里面表示所有角色,用set标签
			<set table="第三张表的名称">
				<key column="配置当前映射文件在第三张表外键的名称"></key>
				<many-to-many class="" column="角色在第三张表中外键名称"></many-to-many>
			</set>
			在角色里面表示所有用户,用set标签
			<set table="第三张表的名称">
				<key column="配置当前映射文件在第三张表外键的名称"></key>
				<many-to-many class="" column="角色在第三张表中外键名称"></many-to-many>
			</set>

	4、在核心配置文件中引入映射文件

多对多级联保存
	1、在用户配置文件中set标签进行配置,cascade值save-update
	2、创建用户和角色对象,把用户方用户里面,最终保存用户就可以
多对多级联删除
	1、在set标签进行配置,cascade值delete	
	2、先查再删,session.delete();
维护第三张表关系
	用户和角色多对多关系,维护关系通过第三张表维护
	让某个用户有某个角色
	1、根据id查询用户和角色
	2、把角色放到用户里面
		把角色对象放到用户set集合
	让某个用户没有某个角色
	1、根据id查询用户和角色
	2、从用户对象删除角色
		在用户set集合删除角色对象

3、一对一
Hibernate查询方式
1、对象导航查询
根据id查询某个客户,再想查询客户里面所有的联系人

SessionFactory sessionFactory = null
Session session = null;
Transaction tx = null;
try{
	sessionFactory = HibernateUtils.getSessionFactory();
	session = sessionFactroy.openSession();
	tx = session.beginTransaction();

	//查询cid=1的客户,再查询这个客户里面所有联系人
	Customer customer = session.get(Customer.class, 1);
	//直接得到客户里面所有联系人的set集合
	ser<linkMan> linkman = customer.getSetLinkMan();

	tx.xommit();
}catch(Exception e){
	tx.rollback();
}finally{
	session.close();
	sessionFactory.close();
}

2、OID查询
根据id查询某一条记录,返回对象

根据id查询记录,调用session里面的get方法
	Customer customer = session.get(Customer.class, 1);

3、hql查询
Query对象,写hql语句实现查询

hql:hibernate query language
区别:普通sql操作数据库表和字段,hql操作实体类和属性
常用的hql语句
·查询所有
	Query query= session.createQuery("from 实体类名称");
	List<实体类名称> list = query.list();
·条件查询
	hql支持 实体类别名.实体类属性 的格式
		from 实体类名称 实体类别名 where 实体类别名.实体类属性名称=? and 实体类别名.实体类属性名称=?
	from 实体类名称 where 实体类属性名称=? and 实体类属性名称=?
	Query query = session.createQuery("...");
	//设置条件值
	query.setParameter(int i, Object obj);
	//第一个参数是问号的位置,第二个参数具体参数值,问号的位置是0开始的

	条件查询模糊查询
	from Customer c where c.custName like ? //c是别名
	_值_
	%值

·排序查询
	Query query = session.createQuery();
	from 实体类名称 orber by 实体类属性名称 asc/desc

·分页查询
	Query对象封装了两个方法实现分页操作:
	//查询所有
	Query query = session.createQuery("from Customer");
	//设置分页数据
	设置开始位置:
	query.setFirstResult(0);
	//设置每页显示的记录数
	query.setMaxResult(4);
	//调用方法调用最终的结果
	List<Customer> list = query.list();

·投影查询
	select 实体类属性名1,实体类属性名2 from 实体类名称
	select后面不支持 * 号
	Query query = session.createQuery();

·聚集函数使用
	select count(*) from Customer
	select sum(*) from Customer
	select avg(*) from Customer
	select max(*) from Customer
	select min(*) from Customer
	Query query = session.createQuery("");
	调用方法得到结果
	Object obj = query.uniqueResult();//注意,这个返回的Object类型实际是long类型,如果要转换成int类型,先要强转long类型,再转int类型
	
使用hql查询操作时候,使用Query对象实现
1、创建Query对象,写hql语句
2、调用query对象方法得到结果

·多表查询
内连接查询hql语句写法
	以客户和联系人为例
	form 客户实体类 别名 inner join 别名.setLinkMan集合 //别名可以不要
	from Customer c inner join c.setLinkMan;	

左外连接
	from Customer c left outer join c.setLinkMan
	迫切左外连接:from Customer c left outer join fetch c.setLinkMan

4、QBC查询
Criteria对象

使用qbc时候,不需要写语句,写方法就可以,使用qbc时候,操作实体类和属性
1、创建Criteria对象
2、调用方法

·查询所有
	Criteria c = session.createCriteria(Customer.class);
	List<Customer> list = c.list();

·条件查询
	Criteria c = session.createCriteria(Customer.class);
	//使用add方法,,表示设置条件值

	方法(属性,条件值)
	Restrictions.eq 等于
  Restrictions.allEq 使用Map,使用key/value进行多个等于的比对
  Restrictions.gt 大于 >
  Restrictions.ge 大于等于 >=
  Restrictions.lt 小于 <
  Restrictions.le 小于等于 <=
  Restrictions.between 对应SQL的BETWEEN子句
  Restrictions.like 对应SQL的LIKE子句
  Restrictions.in 对应SQL的in子句
  Restrictions.and and关系
  Restrictions.or or关系
	
	多个条件
     //业务:查询出id大于1,名字中带ji的用户
     criteria.add(Restrictions.like("name","%ji%"))
	 criteria.add(Restrictions.gt("id", 1));
	
	
·排序查询
	criteria.addOrder(Order.desc("id"))
·分页查询
	Criteria中提供了两个方法,setFirstResult方法和setMaxResults,一个是数据的开始位置0表示第一条记录,一个是返回的记录数。
	Criteria crit = session.createCriteria(Conft.class);  
    crit.setFirstResult(0);  
    crit.setMaxResults(10);  
    List<Conft> list = crit.list();

·统计查询
	Criteria crit = session.createCriteria(Conft.class); 
	//设置操作 
	crit.setProjection(Projections.rowCount());
	//调用方法得到结果
	Object obj = crit.uniqueResult();//实际是long类型

·离线查询
    Session session = HibernateUtils.getCurrentSession();
    Transaction tr = session.beginTransaction();
    DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
    // 设置查询条件
    criteria.add(Restrictions.eq("lkm_gender", "男"));
    // 查询数据
    List<Linkman> list = criteria.getExecutableCriteria(session).list();
    for (Linkman linkman : list) {
        System.out.println(linkman);
    }
    tr.commit();

5、本地sql查询
SQLQuery对象,使用普通sql实现查询

hibernate检索策略
hibernate检索分为两类
1、立即查询:根据id查询,调用get方法,一调用get方法马上发送查询数据库
2、延迟查询:根据id查询,还有load方法,调用load方法不会马上查询,只有得到对象里面的值的时候才会发送语句查询数据库

posted on 2017-07-27 10:09  长嘴大耳怪  阅读(293)  评论(0编辑  收藏  举报