一、Hibernate简介
Hibernate 是传统 Java 对象和数据库服务器之间的桥梁,用来处理基于 O/R 映射机制和模式的那些对象。
Hibernate 架构是分层的,作为数据访问层,你不必知道底层 API 。Hibernate 利用数据库以及配置数据来为应用程序提供持续性服务(以及持续性对象)。
配置对象
配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造。它代表了 Hibernate 所需一个配置或属性文件。配置对象提供了两种基础组件。
-
- 数据库连接:由 Hibernate 支持的一个或多个配置文件处理。这些文件是 hibernate.properties 和 hibernate.cfg.xml。
- 类映射设置:这个组件创造了 Java 类和数据库表格之间的联系。
SessionFactory 对象
配置对象被用于创造一个 SessionFactory 对象,使用提供的配置文件为应用程序依次配置 Hibernate,并允许实例化一个会话对象。SessionFactory 是一个线程安全对象并由应用程序所有的线程所使用。
SessionFactory 是一个重量级对象所以通常它都是在应用程序启动时创造然后留存为以后使用。每个数据库需要一个 SessionFactory 对象使用一个单独的配置文件。所以如果你使用多种数据库那么你要创造多种 SessionFactory 对象。
Session 对象
一个会话被用于与数据库的物理连接。Session 对象是轻量级的,并被设计为每次实例化都需要与数据库的交互。持久对象通过 Session 对象保存和检索。
Session 对象不应该长时间保持开启状态因为它们通常情况下并非线程安全,并且它们应该按照所需创造和销毁。
Transaction 对象
一个事务代表了与数据库工作的一个单元并且大部分 RDBMS 支持事务功能。在 Hibernate 中事务由底层事务管理器和事务(来自 JDBC 或者 JTA)处理。
这是一个选择性对象,Hibernate 应用程序可能不选择使用这个接口,而是在自己应用程序代码中管理事务。
Query 对象
Query 对象使用 SQL 或者 Hibernate 查询语言(HQL)字符串在数据库中来检索数据并创造对象。一个查询的实例被用于连结查询参数,限制由查询返回的结果数量,并最终执行查询。
Criteria 对象
Criteria 对象被用于创造和执行面向规则查询的对象来检索对象。
二、基础知识
1.基础配置
a.需要的jar包
b.创建实体类Product用于映射数据库中的表product
1 package hibernate.pojo; 2 3 public class Product { 4 int id; 5 String name; 6 float price; 7 public int getId() { 8 return id; 9 } 10 public void setId(int id) { 11 this.id = id; 12 } 13 public String getName() { 14 return name; 15 } 16 public void setName(String name) { 17 this.name = name; 18 } 19 public float getPrice() { 20 return price; 21 } 22 public void setPrice(float price) { 23 this.price = price; 24 } 25 26 }
c.配置Product.hbm.xml
在包hibernate.pojo下 新建一个配置文件Product.hbm.xml, 用于映射Product类对应数据库中的product表
文件名中P一定要大写,要和类保持一致。
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping package="hibernate.pojo"> 7 <class name="Product" table="product"> 8 <id name="id" column="id"> 9 <generator class="native"> 10 </generator> 11 </id> 12 <property name="name" /> 13 <property name="price" /> 14 </class> 15 </hibernate-mapping>
<class name="Product" table="product">表示Product类对应数据库中表product。
<id>表示属性id,映射表里面的字段id。<generator class="native">意味着id的自增长方式采用数据库的本地方式。
<property name="name" />这里配置的时候,只写了属性name,没有通过column="name" 显式的指定字段,那么字段的名字也是name,另一个字段price同理。
d.配置hibernate.cfg.xml
在src目录下创建 hibernate.cfg.xml,配置访问数据库要用到的驱动,url,账号密码等等。
其他配置及含义:
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>这表示使用MYSQL方言。 什么方言呢? 因为在代码层面,开发人员不用关心底层到底用Oracle还是Mysql,写的代码都是一样的。 可是Oracle和Mysql所用的sql语句的语法是有所区别的,那么这件事就交给Hibernate来做了。这个时候就需要告诉Hibernate底层用的是什么数据库,它才知道应该用什么样的“方言” 去对话。
<property name="current_session_context_class">thread</property>这是Hibernate事务管理方式,即每个线程一个事务
<property name="show_sql">true</property>这表示是否在控制台显示执行的sql语句
<property name="hbm2ddl.auto">update</property>这表示是否会自动更新数据库的表结构,有这句话,其实是不需要创建表的,因为Hibernate会自动去创建表结构
<mapping resource="com/how2java/pojo/Product.hbm.xml" />这表示Hibernate会去识别Product这个实体类
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 5 6 <hibernate-configuration> 7 8 <session-factory> 9 <!-- Database connection settings --> 10 <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 11 <property name="connection.url">jdbc:mysql://localhost:3306/tests?characterEncoding=UTF-8</property> 12 <property name="connection.username">root</property> 13 <property name="connection.password">123456</property> 14 <!-- SQL dialect --> 15 <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 16 <property name="current_session_context_class">thread</property> 17 <property name="show_sql">true</property> 18 <property name="hbm2ddl.auto">update</property> 19 <mapping resource="hibernate/pojo/Product.hbm.xml" /> 20 </session-factory> 21 </hibernate-configuration>
e.测试类
创建一个Product对象,并通过hibernate把这个对象,插入到数据库中
hibernate的基本步骤是:
1. 获取SessionFactory
2. 通过SessionFactory 获取一个Session
3. 在Session基础上开启一个事务
4. 通过调用Session的save方法把对象保存到数据库
5. 提交事务
6. 关闭Session
7. 关闭SessionFactory
1 package hibernate.test; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 7 import hibernate.pojo.Product; 8 9 public class test { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 14 SessionFactory sFactory = new Configuration().configure().buildSessionFactory(); 15 Session session = sFactory.openSession(); 16 session.beginTransaction(); 17 18 for (int i = 1; i <= 10; i++) { 19 Product product = new Product(); 20 if (i == 10) { 21 product.setName("iphone X"); 22 } else { 23 product.setName("iphone " + i); 24 } 25 product.setPrice(i * 1000); 26 session.save(product); 27 } 28 session.getTransaction().commit(); 29 session.close(); 30 sFactory.close(); 31 } 32 33 }
2.对象状态
-
-
瞬时状态(Transient)
-
通过new创建对象后,对象并没有立刻持久化,它并未与数据库中的数据有任何关联,此时Java对象的状态为瞬时状态。
Session对于瞬时状态的Java对象是一无所知的,当对象不再被其他对象引用时,它的所有数据也就丢失了,对象将会被Java虚拟机按照垃圾回收机制处理。
-
-
持久状态(Persistent)
-
当对象与Session关联,被Session管理时,它就处于持久状态。处于持久状态的对象拥有数据库标识(数据库中的主键值)。
那么,对象是什么时候与Session发生关联的呢?有两种方法:
第一种,通过Sesison的查询接口,或者get()方法,或者load()方法从数据库中加载对象的时候,加载的对象是与数据库表中的一条记录关联的,此时对象与加载它的 Session发生关联;
第二种,瞬时状态的对象,通过Session的save()方法或SaveOrUpdate()方法时,Java对象也与Session发生关联。
对于处于持久状态的对象,Session会持续跟踪和管理它们,如果对象的内部状态发生了任何变更,Hibernate会选择合适的时机(如事务提交时)将变更固化到数据库中。
-
-
游离状态
-
处于持久状态的对象,脱离与其关联的nSession的管理后,对象就处于游离状态。
处于游离状态的对象,Session无法保证对象所包含的数据与数据库中的记录一直,因为Hibernate已经无法感知对该对象的任何操作。
Session提供了两个方法(update()、merge()),将处于游离状态的对象,与一个新的Session发生关联。
此时,对象的状态就从游离状态重新转换为持久状态。
三种状态之间的转换:
<1> .瞬时状态转为持久状态
使用Session对象的save()或saveOrUpdate()方法保存对象后,该对象的状态由瞬时状态转换为持久状态。
使用Session对象的get()或load()方法获取对象,该对象的状态是持久状态。
<2>. 持久状态转为瞬时状态
执行Session对象的delete()方法后,对象由原来的持久状态变为瞬时状态,因为此时该对象没有与任何的数据库数据关联。
<3>. 持久状态转为游离状态
执行了Session对象的evict()、clear()或close()方法,对象由原来的持久状态转为游离状态。
<4> .游离状态转为持久状态
重新获取Session对象,执行Session对象的update()或saveOrUpdate()方法,对象由游离状态转为持久状态,该对象再次与Session对象相关联。
<5>. 游离状态转为瞬时状态
执行Session对象的delete()方法,对象由游离状态转为瞬时状态。
处于瞬时状态或游离状态的对象不再被其他对象引用时,会被Java虚拟机按照垃圾回收机制处理。
1 package hibernate.test; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 7 import hibernate.pojo.Product; 8 9 public class test2 { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 14 SessionFactory sFactory = new Configuration().configure().buildSessionFactory(); 15 Session session = sFactory.openSession(); 16 session.beginTransaction(); 17 Product product = new Product(); 18 product.setName("test2"); 19 System.out.println("此时product是临时状态"); 20 session.save(product); 21 System.out.println("此时product是持久状态"); 22 session.getTransaction().commit(); 23 session.close(); 24 System.out.println("此时product是游离状态"); 25 sFactory.close(); 26 } 27 28 }
3.获取
调用Session的get方法,根据id获取对象。 除了id之外,还需要传递一个类对象,毕竟需要知道获取的是哪个对象
1 package hibernate.test; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 7 import hibernate.pojo.Product; 8 9 public class test3 { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 14 SessionFactory sFactory = new Configuration().configure().buildSessionFactory(); 15 Session session = sFactory.openSession(); 16 session.beginTransaction(); 17 Product product = (Product) session.get(Product.class, 3); 18 System.out.println("id=3的产品为:" + product.getName()); 19 session.getTransaction().commit(); 20 session.close(); 21 sFactory.close(); 22 } 23 24 }
4.删除
1 package hibernate.test; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 7 import hibernate.pojo.Product; 8 9 public class test3 { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 14 SessionFactory sFactory = new Configuration().configure().buildSessionFactory(); 15 Session session = sFactory.openSession(); 16 session.beginTransaction(); 17 18 Product product = (Product) session.get(Product.class, 3); 19 session.delete(product) 20 session.getTransaction().commit(); 21 session.close(); 22 sFactory.close(); 23 } 24 25 } 26
5.修改
1 package hibernate.test; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 7 import hibernate.pojo.Product; 8 9 public class test3 { 10 11 public static void main(String[] args) { 12 // TODO Auto-generated method stub 13 14 SessionFactory sFactory = new Configuration().configure().buildSessionFactory(); 15 Session session = sFactory.openSession(); 16 session.beginTransaction(); 17 18 Product product = (Product) session.get(Product.class, 3); 19 System.out.println("id=3的产品为:" + product.getName()); 20 product.setName("iphone-11"); 21 session.update(product); 22 session.getTransaction().commit(); 23 session.close(); 24 sFactory.close(); 25 } 26 27 }
6.查询-hql
使用HQL,根据name字段进行模糊查询。
1. 首先根据hql创建一个Query对象
2. 设置参数(和基1的PreparedStatement不一样,Query是基0的)
3. 通过Query对象的list()方法即返回查询的结果了。
注: 使用hql的时候,用的是类名Product,而不是表名product_
注: 使用hql的时候,不需要在前面加 select *
7.查询-criteria
使用Criteria 查询数据
1. 通过session的createCriteria创建一个Criteria 对象
2. Criteria.add 增加约束。 在本例中增加一个对name的模糊查询(like)
3. 调用list()方法返回查询结果的集合
除此之外,Criteria 还可以很方便的进行进行分页查询和获取总数
8.查询-标准sql
使用Session的createSQLQuery方法执行标准SQL语句
因为标准SQL语句有可能返回各种各样的结果,比如多表查询,分组统计结果等等。 不能保证其查询结果能够装进一个Product对象中,所以返回的集合里的每一个元素是一个对象数组。 然后再通过下标把这个对象数组中的数据取出来。
代码示例(6——8):
1 package hibernate.test; 2 3 import java.util.List; 4 5 import org.hibernate.Criteria; 6 import org.hibernate.Query; 7 import org.hibernate.Session; 8 import org.hibernate.SessionFactory; 9 import org.hibernate.cfg.Configuration; 10 import org.hibernate.criterion.Restrictions; 11 12 import hibernate.pojo.Product; 13 14 public class testHQLCriteriaSQL { 15 16 public static void main(String[] args) { 17 // TODO Auto-generated method stub 18 19 SessionFactory sFactory = new Configuration().configure().buildSessionFactory(); 20 Session session = sFactory.openSession(); 21 session.beginTransaction(); 22 23 String name = "iphone"; 24 25 Query query = session.createQuery("from Product p where p.name like ?"); 26 query.setString(0, "%" + name + "%"); 27 List<Product> products = query.list(); 28 for (Product p : products) { 29 System.out.print(p.getId() + "\t"); 30 System.out.print(p.getName() + "\t"); 31 System.out.print(p.getPrice()); 32 System.out.println(); 33 } 34 35 Criteria criteria = session.createCriteria(Product.class); 36 criteria.add(Restrictions.like("name", "%" + name + "%")); 37 List<Product> products2 = criteria.list(); 38 for (Product p : products2) { 39 System.out.println(p.getName()); 40 } 41 System.out.println("总数:" + criteria.list().size()); 42 43 String sqlString = "select * from Product p where p.name like '%" + name + "%'"; 44 Query query2 = session.createSQLQuery(sqlString); 45 List<Object[]> list = query2.list(); 46 for (Object[] os : list) { 47 for (Object filed : os) { 48 System.out.print(filed + "\t"); 49 } 50 System.out.println(); 51 } 52 session.getTransaction().commit(); 53 session.close(); 54 sFactory.close(); 55 } 56 57 }