一、hibernate中的实体类的规则
1.1、实体类创建的注意事项
⑴、持久化类提供无参数构造
⑵、成员变量私有,提供公有的get/set方法访问.需提供属性。(属性是指set/get方法,单是成员变量不是属性)
⑶、持久化类中的属性,应尽量使用包装类型。(如果遇到基本数据类型Int,float,double…,无脑使用包装类Integer、Float、Double…..修饰成员变量)
⑷、持久化类需要提供oid.与数据库中的主键列对应。(没有主键的表无法映射到hibernate框架中)
⑸、不要用final修饰class。(hibernate使用cglib代理生成代理对象.代理对象是继承被代理对象.如果被final修饰.将无法生成代理.)
1.2、主键类型
⑴、自然主键(少见)
表的业务列中,有某业务列符合,必须有,并且不重复的特征时,该列可以作为主键使用.
⑵、代理主键(常见)
表的业务列中,没有某业务列符合,必须有,并且不重复的特征时,创建一个没有业务意义的列作为主键
1.3、主键生成策略
⑴、代理主键
identity : 主键自增,由数据库来维护主键值.录入时不需要指定主键;
sequence: Oracle中的主键生成策略;
increment(了解): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值;
hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.;
native:hilo+sequence+identity 自动三选一策略;
uuid: 产生随机字符串作为主键. 主键类型必须为string 类型;
⑵、自然主键
assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入。
如下,对【Customer.hbm.xml】配置主键生成策略
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping SYSTEM "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="hibernate.hnu.domain">
<class name="hibernate.hnu.domain.Customer" table="cst_customer">
<id name="cust_id" column="cust_id">
<!--generator;主键生成策略
就是每条记录录入时,主键的生成规则
identity:主键自增,由数据库维护主键值,录入时不需要指定主键
sequence:Oracre中的主键生成策略
increment(了解):主键自增,由hibernate来维护,每次插入时会先查询表中id最大值,+1作为主键
hilo(了解):高级应用算法,主键自增,由hibernate来维护,开发时不使用
native:hilo+sequence+identity 自动三选一策略
uuid:产生随机字符串作为主键,组件类型必须是String类型
assigned:自然主键生成策略。hibernate不会管理主键值,由开发人员手动录入主键
-->
<generator class="native"></generator>
</id>
<property name="cust_name" column="cust_name"></property>
<property name="cust_source" column="cust_source"></property>
<property name="cust_industry" column="cust_industry"></property>
<property name="cust_level" column="cust_level"></property>
<property name="cust_linkman" column="cust_linkman"></property>
<property name="cust_phone" column="cust_phone"></property>
<property name="cust_mobile" column="cust_mobile"></property>
</class>
</hibernate-mapping>
二、hibernate中的对象状态
⑴、对象分为三种状态
瞬时状态:没有id,没有在session缓存中
持久化状态:有id,在session缓存中
游离|托管状态:有id,没有在session缓存中.
现在写一个工具类,用于获取session;
【HibernateUtils.java】
package hibernate.hnu.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
//创建一个sessionFactory对象
//保证只有一个sessionFactory对象
private static SessionFactory sessionFactory;
static{
//读取配置文件
Configuration configure = new Configuration().configure();
//根据配置信息,创建sessionFactory对象
sessionFactory = configure.buildSessionFactory();
}
//获得session ==> 获得全新的session
public static Session openSession(){
return sessionFactory.openSession();
}
//获得session ==> 获得与线程绑定的session
public static Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
}
举例说明三种状态
package hibernate.hnu.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HibernateTest2 {
/***************************************************************
三种状态特点
save方法:其实不能理解成保存,理解成瞬时状态转换成持久化状态
主键自增:执行sava方法时,为了将对象转换成持久化状态,必须生成id值,所以需要执行insert语句生成
increment:执行save方法,为了生成id,会执行查询id最大值的sql语句
持久化状态的特点:持久化状态对象的任何变化都会自动同步到数据库中
************************************************************/
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//没有id,没有与session关联,瞬时状态
Customer customer = new Customer();
//瞬时状态
customer.setCust_name("合肥师范学院");
//持久化状态,有id,与session有关联
session.save(customer);
//4、提交事务,关闭资源
transaction.commit();
//session关闭,对象编程游离|托管状态
session.close();
}
}
⑵、三种状态的转换图
三、hibernate进阶-一级缓存
缓存:提高效率.hibernate中的一级缓存也是为了提高操作数据库的效率.
提高效率手段1:提高查询效率
提高效率手段2:减少不必要的修改语句发送
四、hibernate中的事务
4.1、什么是事务
在数据库中,一项事务是由一条或者多条操作数据库的SQL语句组成一个不可分割的工作单元,当事务中的所有操作都正常完整时,整个事务才能被提交到数据库中,如果有一项操作没有完成,则整个事务会回滚。
4.2、事务的四个特性
统称为ACID特性
- 原子性(Atomic):对事务进行的数据修改等操作,要么全部执行,要么全部不执行。
- 一致性(Consistency):数据操作前后,数据的总量保持不变。
- 隔离性(Isolation):提供隔离级别,解决事务并发所产生的问题。
- 持久性(Durability):事务一旦提交,对数据库中数据的改变就应该是永久性的,提交后的其它操作或者故障都不会对其有任何影响。
4.3、事务的并发问题
(1)脏读:一个事务读取到另一个事务未提交的数据。
(2)不可重复读:两次读取到的数据不一样。
(3)幻读|虚读:例如本人删除某个数据库的全部内容的同时,有其他人向数据库中添加数据,本人再次查看数据库时,发现已经全部删除的数据库中还有一条数据。
4.4、事务的隔离级别
(1)读未提交:可能出现脏读、不可重复读、幻读|虚读问题;(什么也没解决)
(2)读已提交:可能出现不可重复读、幻读|虚读问题;(解决脏读)
(3)可重复读:可能出现幻读|虚读问题;(解决脏读和不可重复读)
(4)串行化:没有问题,效率极低。(全解决了)
4.5、(重点)如何在hibernate中指定数据库的隔离级别
<property name="hibernate.connection.isolation">4</property>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<!-- hibernate.properties文件中搜索配置信息 -->
<!-- 5个必选配置 -->
<session-factory>
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库url -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<!-- 数据库链接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库链接密码 -->
<property name="hibernate.connection.password">123456</property>
<!-- 数据库方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 3个可选配置 -->
<!-- 将hibernate生成sql语句打印到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 将hibernate生成sql语句进行格式化,即语法缩进 -->
<property name="hibernate.format_sql">true</property>
<!--自动生成表,如果已经存在则不会再生成,如果表有变动,自动更新表(不会删除任何数据)-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 指定hibernate的隔离级别;
在hibernate-release-5.0.7.Final\project\etc\hibernate.properties文件
中搜 iso
## specify a JDBC isolation level
#hibernate.connection.isolation 1|2|4|8
0001 1 读未提交
0010 2 读已提交
0100 4 可重复读
1000 8 串行化
-->
<property name="hibernate.connection.isolation">4</property>
<!-- 引入orm元数据-->
<mapping resource="hibernate/hnu/domain/Customer.hbm.xml"/>
</session-factory>
</hibernate-configuration>
4.6、(重点)在项目中如何管理事务
(1)业务开始之前打开事务,业务执行之后提交事务. 执行过程中出现异常.回滚事务.
(2)在dao层操作数据库需要用到session对象.在service控制事务也是使用session对象完成. 我们要确保dao层和service层使用的是同一个session对象
(3)在hibernate中,确保使用同一个session的问题,hibernate已经帮我们解决了. 我们开发人员只需要调用sessionFactory.getCurrentSession()方法即可获得与当前线程绑定的session对象
(4)注意1: 调用getCurrentSession方法必须配合主配置中的一段配置
注意2:通过getCurrentSession方法获得的session对象.当事务提交时,session会自动关闭.不要手动调用close关闭.
开始配置:
<property name="hibernate.current_session_context_class">thread</property>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" >
<hibernate-configuration>
<!-- hibernate.properties文件中搜索配置信息 -->
<!-- 5个必选配置 -->
<session-factory>
<!-- 数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库url -->
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<!-- 数据库链接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库链接密码 -->
<property name="hibernate.connection.password">123456</property>
<!-- 数据库方言-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 3个可选配置 -->
<!-- 将hibernate生成sql语句打印到控制台 -->
<property name="hibernate.show_sql">true</property>
<!-- 将hibernate生成sql语句进行格式化,即语法缩进 -->
<property name="hibernate.format_sql">true</property>
<!--自动生成表,如果已经存在则不会再生成,如果表有变动,自动更新表(不会删除任何数据)-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 根据业务调整配置 -->
<!-- 指定hibernate的隔离级别;-->
<property name="hibernate.connection.isolation">4</property>
<!-- 指定session与当前线程绑定 -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 引入orm元数据-->
<mapping resource="hibernate/hnu/domain/Customer.hbm.xml"/>
</session-factory>
</hibernate-configuration>
【测试】
package hibernate.hnu.test;
import org.hibernate.Session;
import hibernate.hnu.utils.HibernateUtils;
public class HibernateTest3 {
public static void testOpenSession(){
//1、获得session
Session session1 = HibernateUtils.openSession();
Session session2 = HibernateUtils.openSession();
System.out.println(session1==session2);
}
public static void testCurrentSession(){
//1、获得与线程绑定的session
Session session1 = HibernateUtils.getCurrentSession();
Session session2 = HibernateUtils.getCurrentSession();
System.out.println(session1==session2);
}
public static void main(String[] args) {
testOpenSession();//false
testCurrentSession();//true
}
}
五、hibernate中的批量查询(概述)
HQL查询-hibernate Query Language(多表查询,不复杂时使用)
Hibernate独家查询语言,属于面向对象的查询语言
5.1、基本查询
数据库中的数据:
【测试代码-查询所有】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//1>书写HQL语句
/************************************************
完整的应该这样写
String hql = "from cn.itcast.domain.Customer";
*************************************************/
String hql = "from Customer";
//2>根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//3>根据查询对象获得查询结果
//返回list结果
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
【控制台】
【测试代码-查询单一】
package hibernate.hnu.test;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//1>书写HQL语句
String hql = "from Customer where cust_id=2L";
//2>根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//3>根据查询对象获得查询结果
//接受唯一的查询结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
【控制台】
【测试代码-占位符】
package hibernate.hnu.test;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//1>书写HQL语句
String hql = "from Customer where cust_id=?";
//2>根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//3>根据查询对象获得查询结果
//设置参数,占位符从0开始,注意mysql操作占位符是从1开始
query.setParameter(0, 2L);
//接受唯一的查询结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
控制台结果跟上面的一样
【测试代码-分页查询】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//1>书写HQL语句
String hql = "from Customer";
//2>根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//3>设置分页信息limit ?,?
//起始从零开始
query.setFirstResult(1);//从索引1开始
query.setMaxResults(3);//每页显示3个条目
//4>根据查询对象获得查询结果
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
5.2、Criteria查询(单表条件查询)
Hibernate自创的无语句面向对象查询
【测试代码-查询所有】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//---------------------------------------------------
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
//---------------------------------------------------
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
【测试代码-条件查询】
package hibernate.hnu.test;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//---------------------------------------------------
//Criteria查询
// > gt
// >= ge
// < lt
// <= le
// == eq
// != ne
// in in
// between and between
// like like
// is not null isNotNll
// is null isNull
// or or
// and and
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//添加查询参数 => 查询cust_id为1的Customer对象
criteria.add(Restrictions.eq("cust_id", 2L));
//执行查询获得结果
Customer customer = (Customer) criteria.uniqueResult();
System.out.println(customer);
//---------------------------------------------------
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
【测试代码-分页查询】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//---------------------------------------------------
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置分页信息 limit ?,?
criteria.setFirstResult(1);
criteria.setMaxResults(3);
//list获得结果集
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
//---------------------------------------------------
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
【测试代码:查询总条数】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//---------------------------------------------------
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置查询的聚合函数 => 总行数
Criteria setProjection = criteria.setProjection(Projections.rowCount());
//执行查询
Long uniqueResult = (Long) criteria.uniqueResult();
System.out.println(uniqueResult);
//---------------------------------------------------
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
5.3、原生SQL查询(复杂的业务查询)
【测试代码-查询所有】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//---------------------------------------------------
// 书写SQL语句
String sql = "select * from cst_customer";
// 创建sql查询对象
SQLQuery sqlQuery = session.createSQLQuery(sql);
//指定将结果集封装到哪个对象中
sqlQuery.addEntity(Customer.class);
//调用方法查询结果
List<Customer> list = sqlQuery.list();
for (Customer customer : list) {
System.out.println(customer);
}
//---------------------------------------------------
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
【测试代码-条件查询】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//---------------------------------------------------
// 书写SQL语句
String sql = "select * from cst_customer where cust_id=?";
// 创建sql查询对象
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.setParameter(0, 2L);
//指定将结果集封装到哪个对象中
sqlQuery.addEntity(Customer.class);
//调用方法查询结果
Customer uniqueResult = (Customer) sqlQuery.uniqueResult();
System.out.println(uniqueResult);
//---------------------------------------------------
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}
【测试代码-分页查询】
package hibernate.hnu.test;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.junit.Test;
import hibernate.hnu.domain.Customer;
import hibernate.hnu.utils.HibernateUtils;
public class HqlSearchTest {
@Test
public void fun(){
//1、获得session
Session session = HibernateUtils.openSession();
//2、控制事务
Transaction transaction = session.beginTransaction();
//3、执行操作
//---------------------------------------------------
// 书写SQL语句
String sql = "select * from cst_customer limit ?,?";
// 创建sql查询对象
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.setParameter(0, 1);
sqlQuery.setParameter(1, 3);
//指定将结果集封装到哪个对象中
sqlQuery.addEntity(Customer.class);
//调用方法查询结果
List<Customer> list = sqlQuery.list();
for (Customer customer : list) {
System.out.println(customer);
}
//---------------------------------------------------
//4、提交事务,关闭资源
transaction.commit();
session.close();
}
}