目录
一、hibernate中的实体规则
1.1 实体类创建的规则
1.持久化类要有无参构造函数,方便框架new。
2.成员变量私有,提供get/set方法访问。
3.持久化类中的属性尽量使用包装类型,避免数据库字段有可为NULL的情况。
4.持久化类需要提供id属性,对应数据库的主键。
5.持久化类不能用final修饰,因为hibernate是用cglib来生成对象的,代理对象是继承被代理的对象。
1.2 主键类型
1.2.1 自然主键(逻辑主键)
表的业务中,某些业务字段具有不重复且唯一的特性,比如手机号、身份证等就可以作为主键。
1.2.2 代理主键(物理主键)
表的业务中,没有不重复且唯一的特性,我们就用一个没有业务意义的列,比如id属性来作为主键。
1.3 主键生成策略
1.3.1 代理主键
数据库自动生成,不用手动去管理
sequence:oracle中的主键生成策略。
increment:主键自增,有hibernate来维护,每次插入前查询表中id最大值,作+1操作插入。
hilo:高低位算法,由hibernate来维护,开发时不适用。
native:hilo+sequence+identity(自增主键) 自动三选一。
uuid:随机产生的不重复的字符串,主键类型必须为string。
1.3.2 自然主键
自然主键由开发人员手动录入,hibernate不会管理。
二、hibernate中的实体状态
2.1 三种状态
2.1.1 瞬时状态
没有id,没有在session缓存中。
2.1.2 持久化状态
有id,在session缓存中,当事务提交时,hibernate自动提交到数据库。
2.1.3 游离(托管状态)
有id,没有在session缓存中。
2.2 三种状态的转换图
和EntityFramework中的attach和detach一样额,是否被上线文接管中。
2.3 hibernate中的一级缓存
2.3.1 缓存的原理1
2.3.2 缓存的原理2(快照)
使用快照可减少不必要的修改语句的发送
大致和EF的原理都是一样的。
三、hibernate中的事务
3.1 设置隔离级别
指定hibernate的事务隔离级别
0001 1 读未提交(可以去读未提交的数据,这样肯定会乱 所以脏读、虚读、不可重复读都解决不了)
0010 2 读已提交 (隔离到保证读到的数据是已提交的数据,解决了脏读问题)
0100 4 可重复读 (mysql默认级别)(隔离到保证可以重复读取数据而不出错,解决了脏读和虚读的问题)
1000 8 串行化(解决的所有问题,排队方式访问数据库)
<property name="hibernate.connection.isolation">4</property>
3.2 如何管理事务
一般的,我们是在业务层来手动控制事务。
业务之前打开事务,业务之后提交事务,出现异常,回滚事务。
在dao层和service层都会操作到数据库,我们要保证用的是同一个session对象完成,这样才能确保到事务的控制的一致性。我们使用sessionFactory.getCurrentSession来获取与当前线程绑定的session对象。这里需要配置一下:
<!-- 指定session与当前线程绑定 -->
<property name="hibernate.current_session_context_class">thread</property>
在项目中可以这么使用:
四、hibernate中的查询操作
4.1 HQL查询
HQL全称为Hibernate Query Language,是hibernate独家设计的查询语言,属于面向对象的查询语言,在多表查询但是不复杂的时候常用。
4.1.1 基本查询
@Test
public void testHql(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建hql语句,hql的特点时不含任何和数据库相关的语句、关键字,里边只有面向对象的类名啥的
String hql = "from Customer";
//根据hql创建hql的查询对象,内部自动编译为sql语句
Query query = session.createQuery(hql);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
4.2.2 条件查询
占位符方式:
@Test
public void testHql1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建hql语句,hql的特点时不含任何和数据库相关的语句、关键字,里边只有面向对象的类名啥的
String hql = "from Customer where id = ?";
//根据hql创建hql的查询对象,内部自动编译为sql语句
Query query = session.createQuery(hql);
//设置参数
query.setParameter(0, 3);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
命名占位符:
@Test
public void testHql2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建hql语句,hql的特点时不含任何和数据库相关的语句、关键字,里边只有面向对象的类名啥的
String hql = "from Customer where id = :id";
//根据hql创建hql的查询对象,内部自动编译为sql语句
Query query = session.createQuery(hql);
//设置参数
query.setParameter("id", 2);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
分页查询:
@Test
public void testHql3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建hql语句,hql的特点时不含任何和数据库相关的语句、关键字,里边只有面向对象的类名啥的
String hql = "from Customer";
//根据hql创建hql的查询对象,内部自动编译为sql语句
Query query = session.createQuery(hql);
int page = 1,size = 2;
//设置参数limit ?,?
query.setFirstResult((page-1)*size);
query.setMaxResults(size);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
4.2 Criteria查询
Criteria是hibernate自创的面向对象的无语局的查询,适合单表查询。
4.2.1 基本查询
@Test
public void testCriteria(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建和Customer类相关的Criteria(标准,条件)对象
Criteria query = session.createCriteria(Customer.class);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
4.2.2 条件查询
@Test
public void testCriteria1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建和Customer类相关的Criteria(标准,条件)对象
Criteria query = session.createCriteria(Customer.class);
//设置条件表达式
query.add(Restrictions.eq("id", 2));
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
Restrictions.eq("id", 2) 相当于c#中的Expression一样,这里会生成一个表达式树,然后根据表达式树生成sql。类似的还有
> gt
>= ge
< lt
<= le
== eq
!= ne
in in
between and between
like like
is not null isNotNull
is null isNull
or or
and and
4.2.3 分页查询
@Test
public void testCriteria3(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建和Customer类相关的Criteria(标准,条件)对象
Criteria query = session.createCriteria(Customer.class);
int page = 1,size = 2;
query.setFirstResult((page-1)*size);
query.setMaxResults(size);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
4.2.4 设置查询记录总数
@Test
public void testCriteria4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//创建和Customer类相关的Criteria(标准,条件)对象
Criteria query = session.createCriteria(Customer.class);
//设置要查询的聚合函数或者sql语句
query.setProjection(Projections.rowCount());
Long count = (Long)query.uniqueResult();
//关闭资源
System.out.println(count);
tx.commit();
}
4.3 原生Sql查询
我们可以写原生的sql查询,hibernate帮我们去封装成对象。
4.3.1 基本查询
@Test
public void testSql(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
String sql = "select * from customer";
//创建一个sqlquery查询对象
SQLQuery query = session.createSQLQuery(sql);
//设置映射的实体类
query.addEntity(Customer.class);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
4.3.2 条件查询
@Test
public void testSql1(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
String sql = "select * from customer where id = ?";
//创建一个sqlquery查询对象
SQLQuery query = session.createSQLQuery(sql);
//设置映射的实体类
query.setParameter(0,2);
query.addEntity(Customer.class);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
4.3.2 分页查询
@Test
public void testSql2(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
String sql = "select * from customer limit ?,?";
//创建一个sqlquery查询对象
SQLQuery query = session.createSQLQuery(sql);
//设置映射的实体类
query.setParameter(0,1);
query.setParameter(1, 2);
query.addEntity(Customer.class);
List<Customer> list = query.list();
//关闭资源
System.out.println(list);
tx.commit();
}
五、总结
今天我们学了hibernate的查询方式,需要灵活使用。