SlideShare uma empresa Scribd logo
1 de 237
Hibernate
本课程简介 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Java 对象持久化技术概述 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
应用程序的分层体系结构发展 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
软件层的特征   ,[object Object],[object Object]
软件分层的优点   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Java 应用的持久化层
Hibernate 是持久化层的一种实现方式
软件的模型   ,[object Object],[object Object],[object Object],[object Object]
模型之间的关系
概念模型 ,[object Object],[object Object],[object Object],[object Object]
购物网站应用的概念模型
实体与实体之间存在三种关系   ,[object Object],[object Object],[object Object],[object Object],[object Object]
关系数据模型  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
表的主键 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
表与表之间的参照完整性   用连接表表示多对多关系
域模型   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
域对象 ,[object Object],[object Object],[object Object],[object Object]
实体域对象 ,[object Object],[object Object],[object Object],[object Object]
过程域对象  ,[object Object],[object Object],[object Object],[object Object],[object Object]
事件域对象  ,[object Object],[object Object]
域对象之间的关系  ,[object Object],[object Object],[object Object],[object Object]
关联关系
依赖关系 在 BusinessService 类中访问 Customer 类的方法,并且构造 Customer 类的实例
聚集关系 ,[object Object]
一般化关系 ,[object Object]
域对象的持久化概念
域对象的持久化概念 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
通过 JDBC API 来持久化实体域对象   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
JDBC API
负责持久化 Customer 对象的 BusinessService ,[object Object],[object Object],[object Object],[object Object],[object Object]
业务逻辑代码与数据访问代码耦合的 saveCustomer() 方法 con=getConnection(); // 获得数据库连接  // 开始一个数据库事务  con.setAutoCommit(false);  // 以下是业务逻辑代码,检查客户姓名是否为空  if(customer.getName()==null)  throw new BusinessException(" 客户姓名不允许为空 ");  // 以下是数据访问代码,持久化 Customer 对象  // 为新的 CUSTOMERS 记录分配惟一的 ID  long customerId=getNextId(con,"CUSTOMERS");  // 把 Customer 对象映射为面向关系的 SQL 语句  stmt=con.prepareStatement("insert into CUSTOMERS(ID,NAME,AGE) values(?,?,?)");  stmt.setLong(1,customerId);  stmt.setString(2,customer.getName());  stmt.setInt(3,customer.getAge());  stmt.execute();
业务逻辑代码与数据访问代码耦合的 saveCustomer() 方法 Iterator iterator =customer.getOrders().iterator();  while (iterator.hasNext() ) {  // 以下是业务逻辑代码,检查订单编号是否为空  Order order=(Order)iterator.next();  if(order.getOrderNumber()==null)  throw new BusinessException(" 订单编号不允许为空 ");  // 以下是数据访问代码,级联持久化 Order 对象  // 为新的 ORDERS 记录分配惟一的 ID  long orderId=getNextId(con,"ORDERS");  // 把 Order 对象映射为面向关系的 SQL 语句  stmt=con.prepareStatement("insert into ORDERS(ID,ORDER_NUMBER,PRICE,CUSTOMER_ID)values(?,?,?,?)");  stmt.setLong(1,orderId);  stmt.setString(2,order.getOrderNumber());  stmt.setDouble(3,order.getPrice());  stmt.setLong(4,customerId);  stmt.execute();  }  // 提交数据库事务  con.commit();
JDBC 编程的缺点 ,[object Object],[object Object],[object Object],[object Object]
数据访问模式 ,[object Object],[object Object],[object Object],[object Object],[object Object]
ORM 模式
对象 - 关系映射 (Object-Relation Mapping) 的概念   ,[object Object],[object Object],[object Object]
域模型与关系模型之间存在许多不匹配之处 ,[object Object],[object Object],[object Object],[object Object]
域模型与关系模型之间的不匹配举例 精粒度域模型和粗粒度关系模型
第一个 Hibernate 应用   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
在 Java 应用中使用 Hibernate 的步骤  ,[object Object],[object Object],[object Object],[object Object]
Helloapp 应用的结构
Hibernate 的配置文件 (hibernate.properties)   hibernate.dialect=net.sf.hibernate.dialect.MySQLDialect  hibernate.connection.driver_class=com.mysql.jdbc.Driver  hibernate.connection.url=jdbc:mysql://localhost:3306/SAMPLEDB  hibernate.connection.username=root  hibernate.connection.password=1234  hibernate.show_sql=true
Hibernate 配置文件的属性
创建持久化类 Customer  ,[object Object],[object Object],[object Object]
创建数据库 Schema  create table CUSTOMERS (  ID bigint not null primary key,  NAME varchar(15) not null,  EMAIL varchar(128) not null,  PASSWORD varchar(8) not null,  PHONE int ,  ADDRESS varchar(255),  SEX char(1) ,  IS_MARRIED bit,  DESCRIPTION text,  IMAGE blob,  BIRTHDAY date,  REGISTERED_TIME timestamp  );
创建对象 - 关系映射文件 Customer.hbm.xml   <hibernate-mapping>  <class name=&quot;mypack.Customer&quot; table=&quot;CUSTOMERS&quot;>  <id name=&quot;id&quot; column=&quot;ID&quot; type=&quot;long&quot;>  <generator class=&quot;increment&quot;/>  </id>  <property name=&quot;name&quot;  column=&quot;NAME&quot;  type=&quot;string&quot; not-null=&quot;true&quot; />  <property name=&quot;email&quot;  column=&quot;EMAIL&quot;  type=&quot;string&quot; not-null=&quot;true&quot; />  <property name=&quot;password&quot;  column=&quot;PASSWORD&quot;  type=&quot;string&quot; not-null=&quot;true&quot;/>  <property name=&quot;phone&quot;  column=&quot;PHONE&quot;  type=&quot;int&quot; />  <property name=&quot;address&quot;  column=&quot;ADDRESS&quot;  type=&quot;string&quot; />  <property name=&quot;sex&quot;  column=&quot;SEX&quot;  type=&quot;character&quot;/>  ……   </class>  </hibernate-mapping>
<id> 元素映射 OID   ,[object Object]
<property> 元素映射值类型属性   ,[object Object],[object Object],[object Object]
Java 类型、 Hibernate 映射类型以及 SQL 类型之间的对应关系
Customer.hbm.xml 配置的对象 - 关系映射
采用 XML 文件来配置对象 - 关系映射的优点 ,[object Object],[object Object],[object Object],[object Object]
通过 Hibernate API 操纵数据库
通过 Hibernate API 操纵数据库
创建 BusinessService 类   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Hibernate 的初始化   static{  try{  //  根据默认位置的 Hibernate 配置文件的配置信息,创建一个   //Configuration 实例  Configuration config = new Configuration();  config.addClass(Customer.class);  //  创建 SessionFactory 实例   */  sessionFactory = config.buildSessionFactory();  }catch(Exception e){e.printStackTrace();}  }
Hibernate 的初始化   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
SessionFactory 接口   ,[object Object],[object Object],[object Object]
Session 接口   ,[object Object],[object Object],[object Object],[object Object],[object Object]
Session 接口操纵数据库的方法 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
用 Session 来执行事务的流程   Session session = factory.openSession();  Transaction tx;  try {  // 开始一个事务  tx = session.beginTransaction();  // 执行事务  ...  // 提交事务  tx.commit();  }  catch (Exception e) {  // 如果出现异常,就撤销事务  if (tx!=null) tx.rollback();  throw e;  }  finally {  // 不管事务执行成功与否,最后都关闭 Session  session.close();  }
正常执行数据库事务的流程
saveCustomer() 方法 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
findAllCustomers() 方法 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
loadAndUpdateCustomer () 方法 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
printCustomer() 方法  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
deleteAllCustomers() 方法  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
用 ANT 工具管理项目 ,[object Object],[object Object],[object Object],[object Object],[object Object]
用 ANT 工具管理项目 ,[object Object],[object Object],[object Object],[object Object],[object Object]
映射一对多关联关系   ,[object Object],[object Object],[object Object],[object Object],[object Object]
Customer 和 Order 的一对多双向关联
在 Customer 类中关联 Order 类   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
ORDERS 表参照 CUSTOMERS 表
数据库 Schema  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
映射 Order 类: Order.hbm.xml   <class name=&quot;mypack.Order&quot; table=&quot;ORDERS&quot;>  <id name=&quot;id&quot; type=&quot;long&quot; column=&quot;ID&quot;>  <generator class=&quot;increment&quot;/>  </id>  <property name=&quot;orderNumber&quot; type=&quot;string&quot; >  <column name=&quot;ORDER_NUMBER&quot; length=&quot;15&quot; />  </property>  <many-to-one  name=&quot;customer&quot;  column=&quot;CUSTOMER_ID&quot;  class=&quot;mypack.Customer&quot;  />   </class>  Order 类的 orderNumber 属性为值类型,而 customer 属性为实体类型,实体类型具有单独的 OID 。
<many-to-one> 元素的属性 ,[object Object],[object Object],[object Object]
映射 Customer 类: Customer.hbm.xml   <class name=&quot;mypack.Customer&quot; table=&quot;CUSTOMERS&quot; >  <id name=&quot;id&quot; type=&quot;long&quot; column=&quot;ID&quot;>  <generator class=&quot;increment&quot;/>  </id>  <property name=&quot;name&quot; type=&quot;string&quot; >  <column name=&quot;NAME&quot; length=&quot;15&quot; />  </property>
映射 Customer 类: Customer.hbm.xml (续)  <set  name=&quot;orders&quot;  cascade=&quot;save-update&quot;  inverse= &quot; true&quot;  >  <key column=&quot;CUSTOMER_ID&quot; />  <one-to-many class=&quot;mypack.Order&quot; />  </set>  </class>
<set> 元素的属性 ,[object Object],[object Object],[object Object],[object Object],[object Object]
cascade 属性的取值
级联 保存 Customer 和 Order 对象 tx = session.beginTransaction();  Customer customer=new Customer(&quot;Tom&quot;,new HashSet());  Order order=new Order();  order.setOrderNumber(&quot;Tom_Order001&quot;);  // 建立双向关联关系  order.setCustomer(customer);  customer.getOrders().add(order);  session.save(customer);  tx.commit();
Hibernate 实用工具   Java 源文件 数据库 Schema 对象 - 关系映射文件 hbm2java XDoclet hbm2ddl Middlegen
在 build.xml 中定义 codegen target   <target name=&quot;codegen&quot; depends=&quot;prepare&quot;  description=&quot;Generate Java source from the O/R mapping files&quot;>  <taskdef name=&quot;hbm2java&quot;  lassname=&quot;net.sf.hibernate.tool.hbm2java.Hbm2JavaTask&quot;  classpathref=&quot;project.class.path&quot;/>  <hbm2java output=&quot;${source.root}&quot;>  <fileset dir=&quot;${source.root}&quot;>  <include name=&quot;**/*.hbm.xml&quot;/>  </fileset>  </hbm2java>  </target>
在 build.xml 中定义 schema target   <target name=&quot;schema&quot; depends=&quot;compile&quot;  description=&quot;Generate DB schema from the O/R mapping files&quot;>  <taskdef name=&quot;schemaexport&quot;  classname=&quot;net.sf.hibernate.tool.hbm2ddl.SchemaExportTask&quot;  classpathref=&quot;project.class.path&quot;/>  <schemaexport properties=&quot;${class.root}/hibernate.properties“   quiet=&quot;no&quot; text=&quot;no&quot; drop=&quot;no&quot;  output=&quot;${schema.dir}/sampledb.sql&quot; delimiter=&quot;;&quot;>  <fileset dir=&quot;${class.root}&quot;>  <include name=&quot;**/*.hbm.xml&quot;/>  </fileset>  </schemaexport>  </target>
映射 Category 一对多双向自身关联关系
Category 类的类框图
Category 类的源程序 public class Category implements Serializable{  ……   private Category parentCategory;  private Set childCategories=new HashSet();  public Category getParentCategory(){  return parentCategory;  }  public void setParentCategory(Category parentCategory){  this.parentCategory=parentCategory;  }  public Set getChildCategories(){  return childCategories;  }  public void setChildCategories(Set childCategories){  this.childCategories=childCategories;  }  }
CATEGORIES 表的结构
数据库 Schema ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
映射 parentCategory 属性   <many-to-one  name=&quot;parentCategory&quot;  column=&quot;CATEGORY_ID&quot;  class=&quot;mypack.Category&quot;  />
映射 childCategories 属性   <set  name=&quot;childCategories&quot;  cascade=&quot; all-delete-orphan &quot;  inverse=&quot;true&quot;  >  <key column=&quot;CATEGORY_ID&quot; />  <one-to-many class=&quot;mypack.Category&quot; />  </set>
操纵 Category 对象 ,[object Object],[object Object],[object Object],[object Object]
域对象在持久化层的三种状态   ,[object Object],[object Object],[object Object],[object Object],[object Object]
理解 Session 的缓存   ,[object Object],[object Object]
理解 Session 的缓存   tx = session.beginTransaction();  Customer c1=new Customer(&quot;Tom&quot;,new HashSet());  //Customer 对象被持久化,并且加入到 Session 的缓存中   session.save(c1);  Long id=c1.getId();   //c1 变量不再引用 Customer 对象  c1=null;  // 从 Session 缓存中读取 Customer 对象,使 c2 变量引用 Customer 对象  Customer c2=(Customer)session.load(Customer.class,id);  tx.commit();  // 关闭 Session ,清空缓存  session.close();  // 访问 Customer 对象  System.out.println(c2.getName());  // c2 变量不再引用 Customer 对象 , 此时 Customer 对象结束生命周期。  c2=null;
理解 Session 的缓存   tx = session.beginTransaction();  Customer c1=(Customer)session.load(Customer.class,new Long(1));  Customer c2=(Customer)session.load(Customer.class,new Long(1));  System.out.println(c1==c2);  tx.commit();  session.close();
Session 的缓存的作用 ,[object Object],[object Object]
Session 清理缓存 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
清理缓存的时间点 ,[object Object],[object Object],[object Object],[object Object]
Hibernate 的二级缓存结构   ,[object Object],[object Object]
Hibernate 的二级缓存结构
在 Hibernate 应用中 Java 对象的状态   ,[object Object],[object Object],[object Object]
 
Customer 对象的状态转换过程
用 Session 的 update() 方法关联游离对象   Customer customer=new Customer();  customer.setName(&quot;Tom&quot;);  Session session1=sessionFactory.openSession();  Transaction tx1 = session1.beginTransaction();   session1.save(customer);   tx1.commit();  session1.close(); // 此时 Customer 对象变为游离对象  Session session2=sessionFactory.openSession();  Transaction tx2 = session1.beginTransaction();   customer.setName(&quot;Linda&quot;)  // 在和 session2 关联之前修改 Customer 对象的属性   session2.update(customer);  customer.setName(&quot;Jack&quot;);  // 在和 session2 关联之后修改 Customer 对象的属性  tx2.commit();  session2.close();
Session 的 update() 方法 ,[object Object],[object Object],[object Object]
客户层与业务逻辑层之间传递临时对象和游离对象的过程
Hibernate 的检索策略   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
CUSTOMERS 表和 ORDERS 表中的记录
运行 Session 的 find() 方法   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Customer 与 Order 对象的关联对象图
默认的立即检索策略的缺点 ,[object Object],[object Object],[object Object],[object Object],[object Object]
在一对多关联级别使用延迟检索策略 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
在一对多关联级别使用延迟检索策略 ,[object Object],[object Object]
访问没有被初始化的游离状态的集合代理类实例 Session session=sessionFactory.openSession();  tx = session.beginTransaction();  Customer customer=(Customer)session.get(Customer.class,new Long(1));  tx.commit();  session.close();  // 抛出异常  Iterator orderIterator=customer.getOrders().iterator();   执行以上代码,会抛出以下异常:  ERROR LazyInitializer:63 - Exception initializing proxy
延迟检索策略 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
在多对一关联级别使用迫切左外连接检索策略   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
迫切左外连接检索策略   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
在程序中显式指定迫切左外连接检索策略 ,[object Object],[object Object],[object Object]
在程序中显式指定迫切左外连接检索策略 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Hibernate 检索对象的方式 ,[object Object],[object Object],[object Object],[object Object]
Hibernate 提供的检索对象的方式 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
HQL 检索方式   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Session 的 find() 方法以及 Query 接口  ,[object Object],[object Object]
HQL 检索步骤  // 创建一个 Query 对象  Query query=session.createQuery(&quot;from Customer as c where &quot;  +&quot; c.name=:customerName &quot;  +&quot;and c.age=:customerAge &quot; );  // 动态绑定参数  query.setString( &quot;customerName&quot;,&quot;Tom&quot; );  query.setInteger( &quot;customerAge&quot;,21 );  // 执行查询语句,返回查询结果  List result= query.list();
HQL 检索步骤  ,[object Object],[object Object],[object Object]
方法链编程风格   ,[object Object],[object Object],[object Object],[object Object],[object Object]
QBC 检索方式   ,[object Object],[object Object]
QBC 检索方式   // 创建一个 Criteria 对象  Criteria criteria=session.createCriteria(Customer.class);  // 设定查询条件,然后把查询条件加入到 Criteria 中  Criterion criterion1= Expression.like(&quot;name&quot;, &quot;T%&quot;) ;  Criterion criterion2= Expression.eq(&quot;age&quot;, new Integer(21)) ;  criteria=criteria.add(criterion1);  criteria=criteria.add(criterion2);  // 执行查询语句,返回查询结果  List result=criteria.list();
QBC 检索步骤 ,[object Object],[object Object],[object Object],[object Object]
方法链编程风格   List result=session.createCriteria(Customer.class)  .add(Expression.like(&quot;name&quot;, &quot;T%&quot;)  .add(Expression.eq(&quot;age&quot;, newInteger(21))  .list();
SQL 检索方式  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
分页查询   ,[object Object],[object Object],[object Object]
分页查询   // 采用 HQL 检索方式   Query query = session.createQuery(&quot;from  Customer c  order by c.name asc&quot;);  query.setFirstResult(0);  query.setMaxResults(10);  List result = query.list();   // 采用 QBC 检索方式  Criteria criteria = session.createCriteria(  Customer.class);  criteria.addOrder(  Order.asc(&quot;name&quot;) );  criteria.setFirstResult(0);  criteria.setMaxResults(10);  List result = criteria.list();
迫切左外连接  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],迫切左外连接
投影查询 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
投影查询 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
数据库事务与并发   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
数据库事务的概念 ,[object Object],[object Object],[object Object],[object Object],[object Object]
数据库事务的生命周期
MySQL 数据库系统的客户程序
声明事务的边界 ,[object Object],[object Object],[object Object]
在 mysql.exe 程序中声明事务   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
在自动提交模式下运行事务   ,[object Object],[object Object],[object Object],[object Object],[object Object]
在手工提交模式下运行事务 ,[object Object],[object Object],[object Object],[object Object]
在手工提交模式下运行事务 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
通过 JDBC API 声明事务边界 ,[object Object],[object Object],[object Object],[object Object]
通过 JDBC API 声明事务边界 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
通过 Hibernate API 声明事务边界   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
多个事务并发运行时的并发问题   ,[object Object],[object Object],[object Object],[object Object],[object Object]
取款事务和 支票转账事务 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
并发运行的两个事务导致脏读 取款事务在 T5 时刻把存款余额改为 900 元,支票转账事务在 T6 时刻查询账户的存款余额为 900 元,取款事务在 T7 时刻被撤销,支票转账事务在 T8 时刻把存款余额改为 1000 元。 由于支票转账事务查询到了取款事务未提交的更新数据,并且在这个查询结果的基础上进行更新操作,如果取款事务最后被撤销,会导致银行客户损失 100 元。
并发运行的两个事务导致第二类丢失更新   取款事务在 T5 时刻根据在 T3 时刻的查询结果,把存款余额改为 1000-100 元,在 T6 时刻提交事务。支票转账事务在 T7 时刻根据在 T4 时刻的查询结果,把存款余额改为 1000+100 元。由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失 100 元。
事务隔离级别 ,[object Object],[object Object],[object Object],[object Object],[object Object]
数据库的事务隔离级别
隔离级别与并发性能的关系
设定隔离级别的原则 ,[object Object],[object Object]
在 mysql.exe 程序中设置隔离级别   ,[object Object],[object Object],[object Object],[object Object]
在 Hibernate 中设置隔离级别 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
LockMode ,[object Object],[object Object],[object Object],[object Object],[object Object],* 读数据自动获得,绕过隔离级别和缓存,使用版本检查 ** 写数据自动获得,内部模式,程序中部可以明确指定此模式
悲观锁 Pessimistic Locking ,[object Object],[object Object],[object Object],[object Object],[object Object],*Select  ….  For update
乐观锁 Optimistic Locking ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
使用悲观锁 Account account=(Account)session.get  (Account.class,new Long(1),  LockMode.UPGRADE );  account.setBalance(account.getBalance()-100);  Hibernate 执行的 select 语句为 :  select * from ACCOUNTS  where ID=1 for update ;  update ACCOUNTS set BALANCE=900…
利用悲观锁协调并发运行的取款事务和支票转账事务
使用乐观锁   ,[object Object],[object Object],[object Object],[object Object]
利用 <version> 元素对 ACCOUNTS 表中记录进行版本控制   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
利用 <version> 元素对 ACCOUNTS 表中记录进行版本控制   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
利用 <version> 元素对 ACCOUNTS 表中记录进行版本控制   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
利用 <version> 元素对 ACCOUNTS 表中记录进行版本控制   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
利用 <version> 元素对 ACCOUNTS 表中记录进行版本控制   ,[object Object],[object Object],[object Object]
利用 <version> 元素对 ACCOUNTS 表中记录进行版本控制   try {  tx = session.beginTransaction();  log.write(&quot;transferCheck(): 开始事务 &quot;);  Thread.sleep(500);  Account account=(Account)session.get(Account.class,new Long(1));  log.write(&quot;transferCheck(): 查询到存款余额为: balance=&quot;+account.getBalance());  Thread.sleep(500);  account.setBalance(account.getBalance()+100);  log.write(&quot;transferCheck(): 汇入 100 元,把存款余额改为: &quot;+account.getBalance());  tx.commit(); // 当 Hibernate 执行 update 语句时,可能会抛出 StaleObjectException  log.write(&quot;transferCheck(): 提交事务 &quot;);  Thread.sleep(500);  } catch(StaleObjectStateException e) {  if (tx != null) {  tx.rollback();  }  e.printStackTrace();  System.out.println(&quot; 账户信息已被其他事务修改 , 本事务被撤销,请重新开始支票转账事务 &quot;);  log.write(&quot;transferCheck(): 账户信息已被其他事务修改 , 本事务被撤销 &quot;);  }
利用乐观锁协调并发的取款事务和支票转账事务
实现乐观锁的其他方法   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
使用 JDBC 事务 ,[object Object],[object Object],[object Object]
使用 JTA 事务 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Hibernate FlushMode ,[object Object],[object Object],[object Object]
Hibernate  调用 flush 的时机 ,[object Object],[object Object],[object Object]
映射组成关系 ,[object Object],[object Object],[object Object],[object Object],[object Object]
从粗粒度对象模型到精粒度对象模型   ,[object Object],[object Object]
组成关系的特征 ,[object Object],[object Object],[object Object]
CUSTOMERS 表参照 ADDRESS 表 ,[object Object],以下 SQL 语句用于查询名为 “ Tom” 的客户的家庭地址:  select PROVINCE,CITY,STREET,ZIPCODE from CUSTOMERS as c, ADDRESS as a  where c.HOME_ADDRESS_ID =a.ID and c.NAME= 'Tom';
粗粒度关系数据模型   create table CUSTOMERS (  ID bigint not null,  NAME varchar(15),  HOME_STREET varchar(255),  HOME_CITY varchar(255),  HOME_PROVINCE varchar(255),  HOME_ZIPCODE varchar(255),  COM_STREET varchar(255),  COM_CITY varchar(255),  COM_PROVINCE varchar(255),  COM_ZIPCODE varchar(255),  primary key (ID));
域模型和关系数据模型 域模型中类的数目比关系数据模型中表的数目多
用 <component> 元素来映射 homeAddress 属性   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
用 <component> 元素来映射 homeAddress 属性   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
持久化 Customer 对象   tx = session.beginTransaction();  Customer customer=new Customer();  Address homeAddress=new Address(&quot;province1&quot;,&quot;city1&quot;,&quot;street1&quot;,&quot;100001&quot;,customer);  Address comAddress=new Address(&quot;province2&quot;,&quot;city2&quot;,&quot;street2&quot;,&quot;200002&quot;,customer);  customer.setName(&quot;Tom&quot;);  customer.setHomeAddress(homeAddress);  customer.setComAddress(comAddress);  session.save(customer);  tx.commit();
持久化 Customer 对象   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
试图单独保存一个 Address 对象   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
区分值( Value )类型和实体( Entity )类型  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
区分值( Value )类型和实体( Entity )类型  ,[object Object],[object Object]
区分值( Value )类型和实体( Entity )类型  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Hibernate 与 Struts 集成 ,[object Object],[object Object],[object Object],[object Object],[object Object]
采用 MVC 框架的应用的各个层次之间的依赖关系   ,[object Object]
模型层采用业务代理模式   ,[object Object]
netstore 应用的分层结构
netstore 应用的分层结构   ,[object Object],[object Object],[object Object]
业务代理接口 INetstoreService  public interface INetstoreService extends IAuthentication {  /**  批量检索 Item 对象, beginIndex 参数指定查询结果的起始位置, length 指定检索的 Item  对象的数目。对于 Item 对象的所有集合属性,都使用延迟检索策略   */  public List getItems(int beginIndex,int length) throws DatastoreException;  /**  根据 id 加载 Item 对象   */  public Item getItemById( Long id ) throws DatastoreException;  /**  根据 id 加载 Customer 对象,对于 Customer 对象的 orders 属性,显式采用迫切左外连接检  索策略   */  public Customer getCustomerById( Long id )  throws DatastoreException;  /**  保存或者更新 Customer 对象,并且级联保存或更新它的 orders 集合中的 Order 对象   */  public void saveOrUpdateCustomer(Customer customer )  throws DatastoreException;  /**  保存订单   */  public void saveOrder(Order order) throws DatastoreException;  public void setServletContext( ServletContext ctx );  public void destroy();  }
IAuthentication 接口   public interface IAuthentication {  /**  登出 Web 应用   */  public void logout(String email);  /**  根据客户的 email 和 password 验证身份,如果验证成功,返回  匹配的 Customer 对象,它的 orders 集合属性采用延迟检索策略,  不会被初始化   */  public Customer authenticate(String email, String password) throws  InvalidLoginException,  ExpiredPasswordException,AccountLockedException,  DatastoreException;   }
NetstoreServiceImpl 的 authenticate() 方法 tx = session.beginTransaction();  // 对与 Customer 关联的 Order 对象采用延迟检索策略  Query query = session.createQuery(&quot;from Customer c where  c.email=:email and  c.password=:password&quot;);   query.setString(&quot;email&quot;,email);  query.setString(&quot;password&quot;,password);  List result = query.list();  tx.commit();  if(result.isEmpty())  throw new InvalidLoginException();  return (Customer)result.iterator().next();
NetstoreServiceImpl 的 getCustomerById() 方法 tx = session.beginTransaction();  // 对与 Customer 关联的 Order 对象采用迫切左外连接检索策略  Query query = session.createQuery(&quot;from Customer c  left outer join fetch c.orders where  c.id=:id&quot;);   query.setLong(&quot;id&quot;,id.longValue());  Customer customer =(Customer) query.uniqueResult();  tx.commit();  return customer;
采用适当的检索策略来控制对象图的深度   ,[object Object],[object Object],[object Object],[object Object]
工厂类 NetstoreServiceFactory  ,[object Object],[object Object],[object Object]
NetstoreServiceFactory 的 init() 方法   public void init(ActionServlet servlet, ModuleConfig config)  throws ServletException{  this.servlet = servlet;  // 把服务工厂类本身的实例保存到 application 范围中   servlet.getServletContext().setAttribute( IConstants.SERVICE_FACTORY_KEY, this );   }
NetstoreServiceFactory 的 createService() 方法   public INetstoreService createService() throws  ClassNotFoundException, IllegalAccessException, InstantiationException {  // 从 web.xml 中读取 ActionServlet 的初始化参数 netstore-service-class   String className = servlet.getInitParameter( IConstants.SERVICE_CLASS_KEY );  if (className != null ){serviceClassname = className;}  // 构造业务代理类实例  INetstoreService instance =  (INetstoreService)Class.forName(serviceClassname).newInstance();  instance.setServletContext( servlet.getServletContext() );  return instance;  }
NetstoreServiceFactory 的 createService() 方法   ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Action 类调用 netstore  业务代理接口的时序图
LoginAction 类的 execute() 方法   String email = ((LoginForm)form).getEmail();  String password = ((LoginForm)form).getPassword();  ServletContext context = getServlet().getServletContext();  // 获得业务代理类实例, serviceImpl 被声明为业务代理接口类型,当 INetstoreService 接  // 口的实现发生改变时,不对 Action 类的程序代码构成任何影响。   //getNetstoreService() 方法在 LoginAction 的父类 NetstoreBaseAction 中定义  INetstoreService serviceImpl = getNetstoreService();  // 调用业务代理类的业务方法  Customer  customer= serviceImpl.authenticate(email, password);  SessionContainer existingContainer = getSessionContainer(request);  existingContainer.setCustomer(customer);  return mapping.findForward(IConstants.SUCCESS_KEY);
NetstoreBaseAction 类的 getNetstoreService() 方法   protected INetstoreService getNetstoreService(){  // 从 application 范围内获得代理类工厂  INetstoreServiceFactory factory =  (INetstoreServiceFactory)getApplicationObject(  IConstants.SERVICE_FACTORY_KEY );   INetstoreService service = null;  try{  // 构造代理类实例   service = factory.createService();   }catch( Exception ex ){  log.error( &quot;Problem creating the Netstore Service&quot;, ex );  }  return service;  }
Hibernate 与 EJB 组件 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
JavaBean 与 EJB 的比较 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate
Hibernate

Mais conteúdo relacionado

Destaque

Performance Testing Mobile and Multi-Tier Applications
Performance Testing Mobile and Multi-Tier ApplicationsPerformance Testing Mobile and Multi-Tier Applications
Performance Testing Mobile and Multi-Tier ApplicationsBob Binder
 
AWS Webinar: How to architect and deploy a multi tier share point server farm...
AWS Webinar: How to architect and deploy a multi tier share point server farm...AWS Webinar: How to architect and deploy a multi tier share point server farm...
AWS Webinar: How to architect and deploy a multi tier share point server farm...Amazon Web Services
 
J2EE and layered architecture
J2EE and layered architectureJ2EE and layered architecture
J2EE and layered architectureSuman Behara
 
N-Tier Application Architecture
N-Tier Application ArchitectureN-Tier Application Architecture
N-Tier Application ArchitectureManoj Kumar
 
Web Application Testing
Web Application TestingWeb Application Testing
Web Application TestingRicha Goel
 
Study: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsStudy: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsLinkedIn
 

Destaque (8)

Performance Testing Mobile and Multi-Tier Applications
Performance Testing Mobile and Multi-Tier ApplicationsPerformance Testing Mobile and Multi-Tier Applications
Performance Testing Mobile and Multi-Tier Applications
 
+Fotos2
+Fotos2+Fotos2
+Fotos2
 
AWS Webinar: How to architect and deploy a multi tier share point server farm...
AWS Webinar: How to architect and deploy a multi tier share point server farm...AWS Webinar: How to architect and deploy a multi tier share point server farm...
AWS Webinar: How to architect and deploy a multi tier share point server farm...
 
J2EE and layered architecture
J2EE and layered architectureJ2EE and layered architecture
J2EE and layered architecture
 
N-Tier Application Architecture
N-Tier Application ArchitectureN-Tier Application Architecture
N-Tier Application Architecture
 
J2ee architecture
J2ee architectureJ2ee architecture
J2ee architecture
 
Web Application Testing
Web Application TestingWeb Application Testing
Web Application Testing
 
Study: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving CarsStudy: The Future of VR, AR and Self-Driving Cars
Study: The Future of VR, AR and Self-Driving Cars
 

Semelhante a Hibernate

Windows 8 apps dev.整理及分享
Windows 8 apps dev.整理及分享Windows 8 apps dev.整理及分享
Windows 8 apps dev.整理及分享Liyao Chen
 
Real World ASP.NET MVC
Real World ASP.NET MVCReal World ASP.NET MVC
Real World ASP.NET MVCjeffz
 
JdonFramework中文
JdonFramework中文JdonFramework中文
JdonFramework中文banq jdon
 
前端基础知识回顾
前端基础知识回顾前端基础知识回顾
前端基础知识回顾Wu tianhao
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程appollo0312
 
Learning JavaScript in Three Web Apps(中文)
Learning JavaScript in Three Web Apps(中文)Learning JavaScript in Three Web Apps(中文)
Learning JavaScript in Three Web Apps(中文)Dexter Yang
 
Js高级技巧
Js高级技巧Js高级技巧
Js高级技巧fool2fish
 
事件驱动编程
事件驱动编程事件驱动编程
事件驱动编程banq jdon
 
旺铺前端设计和实现
旺铺前端设计和实现旺铺前端设计和实现
旺铺前端设计和实现hua qiu
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發koji lin
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing江華 奚
 
Great architect cn
Great architect cnGreat architect cn
Great architect cndrewz lin
 
淘宝开放产品前端实践
淘宝开放产品前端实践淘宝开放产品前端实践
淘宝开放产品前端实践taobao.com
 
Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫Justin Lin
 
ASP.NET Core 2.1設計新思維與新發展
ASP.NET  Core 2.1設計新思維與新發展ASP.NET  Core 2.1設計新思維與新發展
ASP.NET Core 2.1設計新思維與新發展江華 奚
 

Semelhante a Hibernate (20)

Metadata4shenzhen Final
Metadata4shenzhen FinalMetadata4shenzhen Final
Metadata4shenzhen Final
 
Windows 8 apps dev.整理及分享
Windows 8 apps dev.整理及分享Windows 8 apps dev.整理及分享
Windows 8 apps dev.整理及分享
 
Real World ASP.NET MVC
Real World ASP.NET MVCReal World ASP.NET MVC
Real World ASP.NET MVC
 
JdonFramework中文
JdonFramework中文JdonFramework中文
JdonFramework中文
 
Structs2簡介
Structs2簡介 Structs2簡介
Structs2簡介
 
前端基础知识回顾
前端基础知识回顾前端基础知识回顾
前端基础知识回顾
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Learning JavaScript in Three Web Apps(中文)
Learning JavaScript in Three Web Apps(中文)Learning JavaScript in Three Web Apps(中文)
Learning JavaScript in Three Web Apps(中文)
 
Js高级技巧
Js高级技巧Js高级技巧
Js高级技巧
 
事件驱动编程
事件驱动编程事件驱动编程
事件驱动编程
 
旺铺前端设计和实现
旺铺前端设计和实现旺铺前端设计和实现
旺铺前端设计和实现
 
山頂洞人日記 - 回歸到最純樸的開發
山頂洞人日記 -  回歸到最純樸的開發山頂洞人日記 -  回歸到最純樸的開發
山頂洞人日記 - 回歸到最純樸的開發
 
Js培训
Js培训Js培训
Js培训
 
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit TestingASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
ASP.NET Core MVC 2.2從開發到測試 - Development & Unit Testing
 
Great architect cn
Great architect cnGreat architect cn
Great architect cn
 
淘宝开放产品前端实践
淘宝开放产品前端实践淘宝开放产品前端实践
淘宝开放产品前端实践
 
Les3
Les3Les3
Les3
 
Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫Java SE 8 技術手冊第 16 章 - 整合資料庫
Java SE 8 技術手冊第 16 章 - 整合資料庫
 
ASP.NET Core 2.1設計新思維與新發展
ASP.NET  Core 2.1設計新思維與新發展ASP.NET  Core 2.1設計新思維與新發展
ASP.NET Core 2.1設計新思維與新發展
 

Hibernate

  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 9.
  • 11.
  • 13.
  • 14.
  • 15.
  • 16. 表与表之间的参照完整性 用连接表表示多对多关系
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 24. 依赖关系 在 BusinessService 类中访问 Customer 类的方法,并且构造 Customer 类的实例
  • 25.
  • 26.
  • 28.
  • 29.
  • 31.
  • 32. 业务逻辑代码与数据访问代码耦合的 saveCustomer() 方法 con=getConnection(); // 获得数据库连接 // 开始一个数据库事务 con.setAutoCommit(false); // 以下是业务逻辑代码,检查客户姓名是否为空 if(customer.getName()==null) throw new BusinessException(&quot; 客户姓名不允许为空 &quot;); // 以下是数据访问代码,持久化 Customer 对象 // 为新的 CUSTOMERS 记录分配惟一的 ID long customerId=getNextId(con,&quot;CUSTOMERS&quot;); // 把 Customer 对象映射为面向关系的 SQL 语句 stmt=con.prepareStatement(&quot;insert into CUSTOMERS(ID,NAME,AGE) values(?,?,?)&quot;); stmt.setLong(1,customerId); stmt.setString(2,customer.getName()); stmt.setInt(3,customer.getAge()); stmt.execute();
  • 33. 业务逻辑代码与数据访问代码耦合的 saveCustomer() 方法 Iterator iterator =customer.getOrders().iterator(); while (iterator.hasNext() ) { // 以下是业务逻辑代码,检查订单编号是否为空 Order order=(Order)iterator.next(); if(order.getOrderNumber()==null) throw new BusinessException(&quot; 订单编号不允许为空 &quot;); // 以下是数据访问代码,级联持久化 Order 对象 // 为新的 ORDERS 记录分配惟一的 ID long orderId=getNextId(con,&quot;ORDERS&quot;); // 把 Order 对象映射为面向关系的 SQL 语句 stmt=con.prepareStatement(&quot;insert into ORDERS(ID,ORDER_NUMBER,PRICE,CUSTOMER_ID)values(?,?,?,?)&quot;); stmt.setLong(1,orderId); stmt.setString(2,order.getOrderNumber()); stmt.setDouble(3,order.getPrice()); stmt.setLong(4,customerId); stmt.execute(); } // 提交数据库事务 con.commit();
  • 34.
  • 35.
  • 37.
  • 38.
  • 40.
  • 41.
  • 43. Hibernate 的配置文件 (hibernate.properties) hibernate.dialect=net.sf.hibernate.dialect.MySQLDialect hibernate.connection.driver_class=com.mysql.jdbc.Driver hibernate.connection.url=jdbc:mysql://localhost:3306/SAMPLEDB hibernate.connection.username=root hibernate.connection.password=1234 hibernate.show_sql=true
  • 45.
  • 46. 创建数据库 Schema create table CUSTOMERS ( ID bigint not null primary key, NAME varchar(15) not null, EMAIL varchar(128) not null, PASSWORD varchar(8) not null, PHONE int , ADDRESS varchar(255), SEX char(1) , IS_MARRIED bit, DESCRIPTION text, IMAGE blob, BIRTHDAY date, REGISTERED_TIME timestamp );
  • 47. 创建对象 - 关系映射文件 Customer.hbm.xml <hibernate-mapping> <class name=&quot;mypack.Customer&quot; table=&quot;CUSTOMERS&quot;> <id name=&quot;id&quot; column=&quot;ID&quot; type=&quot;long&quot;> <generator class=&quot;increment&quot;/> </id> <property name=&quot;name&quot; column=&quot;NAME&quot; type=&quot;string&quot; not-null=&quot;true&quot; /> <property name=&quot;email&quot; column=&quot;EMAIL&quot; type=&quot;string&quot; not-null=&quot;true&quot; /> <property name=&quot;password&quot; column=&quot;PASSWORD&quot; type=&quot;string&quot; not-null=&quot;true&quot;/> <property name=&quot;phone&quot; column=&quot;PHONE&quot; type=&quot;int&quot; /> <property name=&quot;address&quot; column=&quot;ADDRESS&quot; type=&quot;string&quot; /> <property name=&quot;sex&quot; column=&quot;SEX&quot; type=&quot;character&quot;/> …… </class> </hibernate-mapping>
  • 48.
  • 49.
  • 50. Java 类型、 Hibernate 映射类型以及 SQL 类型之间的对应关系
  • 52.
  • 53. 通过 Hibernate API 操纵数据库
  • 54. 通过 Hibernate API 操纵数据库
  • 55.
  • 56. Hibernate 的初始化 static{ try{ // 根据默认位置的 Hibernate 配置文件的配置信息,创建一个 //Configuration 实例 Configuration config = new Configuration(); config.addClass(Customer.class); // 创建 SessionFactory 实例 */ sessionFactory = config.buildSessionFactory(); }catch(Exception e){e.printStackTrace();} }
  • 57.
  • 58.
  • 59.
  • 60.
  • 61. 用 Session 来执行事务的流程 Session session = factory.openSession(); Transaction tx; try { // 开始一个事务 tx = session.beginTransaction(); // 执行事务 ... // 提交事务 tx.commit(); } catch (Exception e) { // 如果出现异常,就撤销事务 if (tx!=null) tx.rollback(); throw e; } finally { // 不管事务执行成功与否,最后都关闭 Session session.close(); }
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71. Customer 和 Order 的一对多双向关联
  • 72.
  • 74.
  • 75. 映射 Order 类: Order.hbm.xml <class name=&quot;mypack.Order&quot; table=&quot;ORDERS&quot;> <id name=&quot;id&quot; type=&quot;long&quot; column=&quot;ID&quot;> <generator class=&quot;increment&quot;/> </id> <property name=&quot;orderNumber&quot; type=&quot;string&quot; > <column name=&quot;ORDER_NUMBER&quot; length=&quot;15&quot; /> </property> <many-to-one name=&quot;customer&quot; column=&quot;CUSTOMER_ID&quot; class=&quot;mypack.Customer&quot; /> </class> Order 类的 orderNumber 属性为值类型,而 customer 属性为实体类型,实体类型具有单独的 OID 。
  • 76.
  • 77. 映射 Customer 类: Customer.hbm.xml <class name=&quot;mypack.Customer&quot; table=&quot;CUSTOMERS&quot; > <id name=&quot;id&quot; type=&quot;long&quot; column=&quot;ID&quot;> <generator class=&quot;increment&quot;/> </id> <property name=&quot;name&quot; type=&quot;string&quot; > <column name=&quot;NAME&quot; length=&quot;15&quot; /> </property>
  • 78. 映射 Customer 类: Customer.hbm.xml (续) <set name=&quot;orders&quot; cascade=&quot;save-update&quot; inverse= &quot; true&quot; > <key column=&quot;CUSTOMER_ID&quot; /> <one-to-many class=&quot;mypack.Order&quot; /> </set> </class>
  • 79.
  • 81. 级联 保存 Customer 和 Order 对象 tx = session.beginTransaction(); Customer customer=new Customer(&quot;Tom&quot;,new HashSet()); Order order=new Order(); order.setOrderNumber(&quot;Tom_Order001&quot;); // 建立双向关联关系 order.setCustomer(customer); customer.getOrders().add(order); session.save(customer); tx.commit();
  • 82. Hibernate 实用工具 Java 源文件 数据库 Schema 对象 - 关系映射文件 hbm2java XDoclet hbm2ddl Middlegen
  • 83. 在 build.xml 中定义 codegen target <target name=&quot;codegen&quot; depends=&quot;prepare&quot; description=&quot;Generate Java source from the O/R mapping files&quot;> <taskdef name=&quot;hbm2java&quot; lassname=&quot;net.sf.hibernate.tool.hbm2java.Hbm2JavaTask&quot; classpathref=&quot;project.class.path&quot;/> <hbm2java output=&quot;${source.root}&quot;> <fileset dir=&quot;${source.root}&quot;> <include name=&quot;**/*.hbm.xml&quot;/> </fileset> </hbm2java> </target>
  • 84. 在 build.xml 中定义 schema target <target name=&quot;schema&quot; depends=&quot;compile&quot; description=&quot;Generate DB schema from the O/R mapping files&quot;> <taskdef name=&quot;schemaexport&quot; classname=&quot;net.sf.hibernate.tool.hbm2ddl.SchemaExportTask&quot; classpathref=&quot;project.class.path&quot;/> <schemaexport properties=&quot;${class.root}/hibernate.properties“ quiet=&quot;no&quot; text=&quot;no&quot; drop=&quot;no&quot; output=&quot;${schema.dir}/sampledb.sql&quot; delimiter=&quot;;&quot;> <fileset dir=&quot;${class.root}&quot;> <include name=&quot;**/*.hbm.xml&quot;/> </fileset> </schemaexport> </target>
  • 87. Category 类的源程序 public class Category implements Serializable{ …… private Category parentCategory; private Set childCategories=new HashSet(); public Category getParentCategory(){ return parentCategory; } public void setParentCategory(Category parentCategory){ this.parentCategory=parentCategory; } public Set getChildCategories(){ return childCategories; } public void setChildCategories(Set childCategories){ this.childCategories=childCategories; } }
  • 89.
  • 90. 映射 parentCategory 属性 <many-to-one name=&quot;parentCategory&quot; column=&quot;CATEGORY_ID&quot; class=&quot;mypack.Category&quot; />
  • 91. 映射 childCategories 属性 <set name=&quot;childCategories&quot; cascade=&quot; all-delete-orphan &quot; inverse=&quot;true&quot; > <key column=&quot;CATEGORY_ID&quot; /> <one-to-many class=&quot;mypack.Category&quot; /> </set>
  • 92.
  • 93.
  • 94.
  • 95. 理解 Session 的缓存 tx = session.beginTransaction(); Customer c1=new Customer(&quot;Tom&quot;,new HashSet()); //Customer 对象被持久化,并且加入到 Session 的缓存中 session.save(c1); Long id=c1.getId(); //c1 变量不再引用 Customer 对象 c1=null; // 从 Session 缓存中读取 Customer 对象,使 c2 变量引用 Customer 对象 Customer c2=(Customer)session.load(Customer.class,id); tx.commit(); // 关闭 Session ,清空缓存 session.close(); // 访问 Customer 对象 System.out.println(c2.getName()); // c2 变量不再引用 Customer 对象 , 此时 Customer 对象结束生命周期。 c2=null;
  • 96. 理解 Session 的缓存 tx = session.beginTransaction(); Customer c1=(Customer)session.load(Customer.class,new Long(1)); Customer c2=(Customer)session.load(Customer.class,new Long(1)); System.out.println(c1==c2); tx.commit(); session.close();
  • 97.
  • 98.
  • 99.
  • 100.
  • 102.
  • 103.  
  • 105. 用 Session 的 update() 方法关联游离对象 Customer customer=new Customer(); customer.setName(&quot;Tom&quot;); Session session1=sessionFactory.openSession(); Transaction tx1 = session1.beginTransaction(); session1.save(customer); tx1.commit(); session1.close(); // 此时 Customer 对象变为游离对象 Session session2=sessionFactory.openSession(); Transaction tx2 = session1.beginTransaction(); customer.setName(&quot;Linda&quot;) // 在和 session2 关联之前修改 Customer 对象的属性 session2.update(customer); customer.setName(&quot;Jack&quot;); // 在和 session2 关联之后修改 Customer 对象的属性 tx2.commit(); session2.close();
  • 106.
  • 108.
  • 109. CUSTOMERS 表和 ORDERS 表中的记录
  • 110.
  • 111. Customer 与 Order 对象的关联对象图
  • 112.
  • 113.
  • 114.
  • 115. 访问没有被初始化的游离状态的集合代理类实例 Session session=sessionFactory.openSession(); tx = session.beginTransaction(); Customer customer=(Customer)session.get(Customer.class,new Long(1)); tx.commit(); session.close(); // 抛出异常 Iterator orderIterator=customer.getOrders().iterator(); 执行以上代码,会抛出以下异常: ERROR LazyInitializer:63 - Exception initializing proxy
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125. HQL 检索步骤 // 创建一个 Query 对象 Query query=session.createQuery(&quot;from Customer as c where &quot; +&quot; c.name=:customerName &quot; +&quot;and c.age=:customerAge &quot; ); // 动态绑定参数 query.setString( &quot;customerName&quot;,&quot;Tom&quot; ); query.setInteger( &quot;customerAge&quot;,21 ); // 执行查询语句,返回查询结果 List result= query.list();
  • 126.
  • 127.
  • 128.
  • 129. QBC 检索方式 // 创建一个 Criteria 对象 Criteria criteria=session.createCriteria(Customer.class); // 设定查询条件,然后把查询条件加入到 Criteria 中 Criterion criterion1= Expression.like(&quot;name&quot;, &quot;T%&quot;) ; Criterion criterion2= Expression.eq(&quot;age&quot;, new Integer(21)) ; criteria=criteria.add(criterion1); criteria=criteria.add(criterion2); // 执行查询语句,返回查询结果 List result=criteria.list();
  • 130.
  • 131. 方法链编程风格 List result=session.createCriteria(Customer.class) .add(Expression.like(&quot;name&quot;, &quot;T%&quot;) .add(Expression.eq(&quot;age&quot;, newInteger(21)) .list();
  • 132.
  • 133.
  • 134. 分页查询 // 采用 HQL 检索方式 Query query = session.createQuery(&quot;from Customer c order by c.name asc&quot;); query.setFirstResult(0); query.setMaxResults(10); List result = query.list(); // 采用 QBC 检索方式 Criteria criteria = session.createCriteria( Customer.class); criteria.addOrder( Order.asc(&quot;name&quot;) ); criteria.setFirstResult(0); criteria.setMaxResults(10); List result = criteria.list();
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152. 并发运行的两个事务导致脏读 取款事务在 T5 时刻把存款余额改为 900 元,支票转账事务在 T6 时刻查询账户的存款余额为 900 元,取款事务在 T7 时刻被撤销,支票转账事务在 T8 时刻把存款余额改为 1000 元。 由于支票转账事务查询到了取款事务未提交的更新数据,并且在这个查询结果的基础上进行更新操作,如果取款事务最后被撤销,会导致银行客户损失 100 元。
  • 153. 并发运行的两个事务导致第二类丢失更新 取款事务在 T5 时刻根据在 T3 时刻的查询结果,把存款余额改为 1000-100 元,在 T6 时刻提交事务。支票转账事务在 T7 时刻根据在 T4 时刻的查询结果,把存款余额改为 1000+100 元。由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失 100 元。
  • 154.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163. 使用悲观锁 Account account=(Account)session.get (Account.class,new Long(1), LockMode.UPGRADE ); account.setBalance(account.getBalance()-100); Hibernate 执行的 select 语句为 : select * from ACCOUNTS where ID=1 for update ; update ACCOUNTS set BALANCE=900…
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171. 利用 <version> 元素对 ACCOUNTS 表中记录进行版本控制 try { tx = session.beginTransaction(); log.write(&quot;transferCheck(): 开始事务 &quot;); Thread.sleep(500); Account account=(Account)session.get(Account.class,new Long(1)); log.write(&quot;transferCheck(): 查询到存款余额为: balance=&quot;+account.getBalance()); Thread.sleep(500); account.setBalance(account.getBalance()+100); log.write(&quot;transferCheck(): 汇入 100 元,把存款余额改为: &quot;+account.getBalance()); tx.commit(); // 当 Hibernate 执行 update 语句时,可能会抛出 StaleObjectException log.write(&quot;transferCheck(): 提交事务 &quot;); Thread.sleep(500); } catch(StaleObjectStateException e) { if (tx != null) { tx.rollback(); } e.printStackTrace(); System.out.println(&quot; 账户信息已被其他事务修改 , 本事务被撤销,请重新开始支票转账事务 &quot;); log.write(&quot;transferCheck(): 账户信息已被其他事务修改 , 本事务被撤销 &quot;); }
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182. 粗粒度关系数据模型 create table CUSTOMERS ( ID bigint not null, NAME varchar(15), HOME_STREET varchar(255), HOME_CITY varchar(255), HOME_PROVINCE varchar(255), HOME_ZIPCODE varchar(255), COM_STREET varchar(255), COM_CITY varchar(255), COM_PROVINCE varchar(255), COM_ZIPCODE varchar(255), primary key (ID));
  • 184.
  • 185.
  • 186. 持久化 Customer 对象 tx = session.beginTransaction(); Customer customer=new Customer(); Address homeAddress=new Address(&quot;province1&quot;,&quot;city1&quot;,&quot;street1&quot;,&quot;100001&quot;,customer); Address comAddress=new Address(&quot;province2&quot;,&quot;city2&quot;,&quot;street2&quot;,&quot;200002&quot;,customer); customer.setName(&quot;Tom&quot;); customer.setHomeAddress(homeAddress); customer.setComAddress(comAddress); session.save(customer); tx.commit();
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 196.
  • 197. 业务代理接口 INetstoreService public interface INetstoreService extends IAuthentication { /** 批量检索 Item 对象, beginIndex 参数指定查询结果的起始位置, length 指定检索的 Item 对象的数目。对于 Item 对象的所有集合属性,都使用延迟检索策略 */ public List getItems(int beginIndex,int length) throws DatastoreException; /** 根据 id 加载 Item 对象 */ public Item getItemById( Long id ) throws DatastoreException; /** 根据 id 加载 Customer 对象,对于 Customer 对象的 orders 属性,显式采用迫切左外连接检 索策略 */ public Customer getCustomerById( Long id ) throws DatastoreException; /** 保存或者更新 Customer 对象,并且级联保存或更新它的 orders 集合中的 Order 对象 */ public void saveOrUpdateCustomer(Customer customer ) throws DatastoreException; /** 保存订单 */ public void saveOrder(Order order) throws DatastoreException; public void setServletContext( ServletContext ctx ); public void destroy(); }
  • 198. IAuthentication 接口 public interface IAuthentication { /** 登出 Web 应用 */ public void logout(String email); /** 根据客户的 email 和 password 验证身份,如果验证成功,返回 匹配的 Customer 对象,它的 orders 集合属性采用延迟检索策略, 不会被初始化 */ public Customer authenticate(String email, String password) throws InvalidLoginException, ExpiredPasswordException,AccountLockedException, DatastoreException; }
  • 199. NetstoreServiceImpl 的 authenticate() 方法 tx = session.beginTransaction(); // 对与 Customer 关联的 Order 对象采用延迟检索策略 Query query = session.createQuery(&quot;from Customer c where c.email=:email and c.password=:password&quot;); query.setString(&quot;email&quot;,email); query.setString(&quot;password&quot;,password); List result = query.list(); tx.commit(); if(result.isEmpty()) throw new InvalidLoginException(); return (Customer)result.iterator().next();
  • 200. NetstoreServiceImpl 的 getCustomerById() 方法 tx = session.beginTransaction(); // 对与 Customer 关联的 Order 对象采用迫切左外连接检索策略 Query query = session.createQuery(&quot;from Customer c left outer join fetch c.orders where c.id=:id&quot;); query.setLong(&quot;id&quot;,id.longValue()); Customer customer =(Customer) query.uniqueResult(); tx.commit(); return customer;
  • 201.
  • 202.
  • 203. NetstoreServiceFactory 的 init() 方法 public void init(ActionServlet servlet, ModuleConfig config) throws ServletException{ this.servlet = servlet; // 把服务工厂类本身的实例保存到 application 范围中 servlet.getServletContext().setAttribute( IConstants.SERVICE_FACTORY_KEY, this ); }
  • 204. NetstoreServiceFactory 的 createService() 方法 public INetstoreService createService() throws ClassNotFoundException, IllegalAccessException, InstantiationException { // 从 web.xml 中读取 ActionServlet 的初始化参数 netstore-service-class String className = servlet.getInitParameter( IConstants.SERVICE_CLASS_KEY ); if (className != null ){serviceClassname = className;} // 构造业务代理类实例 INetstoreService instance = (INetstoreService)Class.forName(serviceClassname).newInstance(); instance.setServletContext( servlet.getServletContext() ); return instance; }
  • 205.
  • 206. Action 类调用 netstore 业务代理接口的时序图
  • 207. LoginAction 类的 execute() 方法 String email = ((LoginForm)form).getEmail(); String password = ((LoginForm)form).getPassword(); ServletContext context = getServlet().getServletContext(); // 获得业务代理类实例, serviceImpl 被声明为业务代理接口类型,当 INetstoreService 接 // 口的实现发生改变时,不对 Action 类的程序代码构成任何影响。 //getNetstoreService() 方法在 LoginAction 的父类 NetstoreBaseAction 中定义 INetstoreService serviceImpl = getNetstoreService(); // 调用业务代理类的业务方法 Customer customer= serviceImpl.authenticate(email, password); SessionContainer existingContainer = getSessionContainer(request); existingContainer.setCustomer(customer); return mapping.findForward(IConstants.SUCCESS_KEY);
  • 208. NetstoreBaseAction 类的 getNetstoreService() 方法 protected INetstoreService getNetstoreService(){ // 从 application 范围内获得代理类工厂 INetstoreServiceFactory factory = (INetstoreServiceFactory)getApplicationObject( IConstants.SERVICE_FACTORY_KEY ); INetstoreService service = null; try{ // 构造代理类实例 service = factory.createService(); }catch( Exception ex ){ log.error( &quot;Problem creating the Netstore Service&quot;, ex ); } return service; }
  • 209.
  • 210.