Hibernate 学习(三)
一、关系映射
实体类之间的关联映射以及表之间的关系是 ORM 的灵魂之处。对象间的关系的子集可以用下列四种方式解释。关联映射可以是单向的也可以是双向的。
映射类型 | 描述 |
---|---|
Many-to-One | 使用 Hibernate 映射多对一关系 |
One-to-One | 使用 Hibernate 映射一对一关系 |
One-to-Many | 使用 Hibernate 映射一对多关系 |
Many-to-Many | 使用 Hibernate 映射多对多关系 |
1、多对一
1、映射文件 Product.hbm.xml 配置:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!--映射文件-->
<hibernate-mapping package="com.hibernate.pojo">
<!--class表示一个由hibernate管理的持久对象,对应数据库中一个表-->
<!--table数据库的表名-->
<!--一方-->
<class name="ProductDir" table="product_dir">
<id name="id" type="int" column="id">
<!--generator表示主键的生成方式,native自动选择数据库本地的策略-->
<generator class="native"/>
</id>
<!--非主键属性-->
<property name="dirNum" column="num" type="string"/>
<property name="dirName" column="name" type="string"/>
</class> <!--多方-->
<class name="Product" table="product">
<id name="id" type="int" column="id">
<!--generator表示主键的生成方式,native自动选择数据库本地的策略-->
<generator class="native"/>
</id>
<!--非主键属性-->
<property name="name" column="name" type="string"/>
<property name="price" column="price" type="float"/> <!--多Product对一ProductDir-->
<many-to-one name="dir" class="ProductDir" column="dir_id"/>
</class>
</hibernate-mapping>
2、pojo设计:
1、多方
package com.hibernate.pojo; /**
* @author zt1994 2018/3/6 14:16
*/
public class Product {
private Integer id;
private String name;
private float price;
private ProductDir dir; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public float getPrice() {
return price;
} public void setPrice(float price) {
this.price = price;
} public ProductDir getDir() {
return dir;
} public void setDir(ProductDir dir) {
this.dir = dir;
}
}
2、一方
package com.hibernate.pojo; /**
* @author zt1994 2018/3/7 15:23
*/
public class ProductDir {
private Integer id;
private String dirNum;
private String dirName; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getDirNum() {
return dirNum;
} public void setDirNum(String dirNum) {
this.dirNum = dirNum;
} public String getDirName() {
return dirName;
} public void setDirName(String dirName) {
this.dirName = dirName;
}
}
3、数据库设计:
1、product 表
2、product_dir 表
4、查询测试
/**
* 测试多对一 查询
*/
@Test
public void testManyToOneQuery(){
//1.获取session
Session session = HibernateUtil.getSession();
Transaction transaction = null;
try {
//2.开启事务
transaction = session.getTransaction();
transaction.begin();
//3.操作CRUD
String hql = "select o from com.hibernate.pojo.Product o";
Query query = session.createQuery(hql);
List<Product> list = query.list();
for (Product product : list) {
System.out.println(product.getDir().getDirName());
}
//4.提交事务
transaction.commit();
} catch (Exception e) {
if (transaction != null) transaction.rollback(); //回滚
e.printStackTrace();
} finally {
//5.关闭资源
session.close();
}
}
5、保存测试
/**
* 保存测试
*/
@Test
public void testManyToOneSave(){
//1.获取session
Session session = HibernateUtil.getSession();
Transaction transaction = null;
try {
//2.开启事务
transaction = session.getTransaction();
transaction.begin();
//3.操作CRUD
//一方(产品类型)
ProductDir productDir = new ProductDir();
productDir.setDirName("类型4"); //多方(产品1)
Product product1 = new Product();
//建立联系
product1.setDir(productDir);
product1.setName("产品1");
//多方(产品2)
Product product2 = new Product();
//建立联系
product2.setDir(productDir);
product2.setName("产品2"); //保存一方产品类型
session.save(productDir);
//保存多方产品1,2
session.save(product1);
session.save(product2); //4.提交事务
transaction.commit();
} catch (Exception e) {
if (transaction != null) transaction.rollback(); //回滚
e.printStackTrace();
} finally {
//5.关闭资源
session.close();
}
}
控制台输出:
注意:如果先保存产品后保存产品类型,控制台输出不一样,
控制台输出:
实际情况,我们先把类型分好,然后进货的时候就直接可以分类。但是如果相反的话,我们就要先进货,再分类型,再把货放到相应类型中去。
2、一对多
1、映射文件 Product.hbm.xml 配置:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!--映射文件-->
<hibernate-mapping package="com.hibernate.pojo">
<!--class表示一个由hibernate管理的持久对象,对应数据库中一个表-->
<!--table数据库的表名-->
<!--一方-->
<class name="ProductDir" table="product_dir">
<id name="id" type="int" column="id">
<!--generator表示主键的生成方式,native自动选择数据库本地的策略-->
<generator class="native"/>
</id>
<!--非主键属性-->
<property name="dirNum" column="num" type="string"/>
<property name="dirName" column="name" type="string"/> <set name="products">
<key column="dir_id"/>
<one-to-many class="Product"/>
</set>
</class> <!--多方-->
<class name="Product" table="product">
<id name="id" type="int" column="id">
<!--generator表示主键的生成方式,native自动选择数据库本地的策略-->
<generator class="native"/>
</id>
<!--非主键属性-->
<property name="name" column="name" type="string"/>
<property name="price" column="price" type="float"/>
</class>
</hibernate-mapping>
2、pojo 设计:
package com.hibernate.pojo; import java.util.HashSet;
import java.util.Set; /**
* @author zt1994 2018/3/7 15:23
*/
public class ProductDir {
private Integer id;
private String dirNum;
private String dirName;
private Set<Product> products = new HashSet<>(); //产品集合 public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getDirNum() {
return dirNum;
} public void setDirNum(String dirNum) {
this.dirNum = dirNum;
} public String getDirName() {
return dirName;
} public void setDirName(String dirName) {
this.dirName = dirName;
} public Set<Product> getProducts() {
return products;
} public void setProducts(Set<Product> products) {
this.products = products;
}
}
3、测试一对多查询
/**
* 测试一对多保存
*/
@Test
public void testOneToManySave(){
//1.获取session
Session session = HibernateUtil.getSession();
Transaction transaction = null;
try {
//2.开启事务
transaction = session.getTransaction();
transaction.begin();
//3.操作CRUD
//一方(产品类型)
ProductDir productDir = new ProductDir();
productDir.setDirName("类型4"); //多方(产品1)
Product product1 = new Product();
product1.setName("产品1");
//多方(产品2)
Product product2 = new Product();
product2.setName("产品2"); //建立关系(只能由一方建立多方关系)
productDir.getProducts().add(product1);
productDir.getProducts().add(product2); //保存一方产品类型
session.save(productDir);
//保存多方产品1,2
session.save(product1);
session.save(product2);
//4.提交事务
transaction.commit();
} catch (Exception e) {
if (transaction != null) transaction.rollback(); //回滚
e.printStackTrace();
} finally {
//5.关闭资源
session.close();
}
}
二、二级缓存
第二级缓存是一种可选择的缓存并且第一级缓存在任何想要在第二级缓存中找到一个对象前将总是被询问。第二级缓存可以在每一个类和每一个集合的基础上被安装,并且它主要负责跨会话缓存对象。
任何第三方缓存可以和 Hibernate 一起使用。org.hibernate.cache.CacheProvider 接口被提供,它必须实现来给 Hibernate 提供一个缓存实现的解决方法。
1、并发策略
一个并发策略是一个中介,它负责保存缓存中的数据项和从缓存中检索它们。如果你将使用一个二级缓存,你必须决定,对于每一个持久类和集合,使用哪一个并发策略。
- Transactional:为主读数据使用这个策略,在一次更新的罕见状况下并发事务阻止过期数据是关键的。
- Read-write:为主读数据再一次使用这个策略,在一次更新的罕见状况下并发事务阻止过期数据是关键的。
- Nonstrict-read-write:这个策略不保证缓存和数据库之间的一致性。如果数据几乎不改变并且过期数据不是很重要,使用这个策略。
- Read-only:一个适合永不改变数据的并发策略。只为参考数据使用它。
2、配置二级缓存
1、拷贝 jar 包
2、配置Hibernate.cfg.xml文件
1、开启二级缓存
hibernate.cache.use_second_level_cache=true
2、添加一个二级缓存的供应商(实现类)
hibernate4的配置:hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
hibernate3的配置:hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
3、开启查询缓存
hibernate.cache.use_query_cache=true
4、配置那个 domain 需要二级缓存(最好添加在映射文件后)
<class-cache class="com.hibernate.day01.model.Product" usage="read-write" />
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <!--hibernate核心配置文件-->
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!--链接池配置-->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/how2java</property>
<property name="connection.username">root</property>
<property name="connection.password">admin</property>
<!--显示sql语句-->
<property name="show_sql">true</property> <!--开启二级缓存-->
<property name="cache.use_second_level_cache">true</property> <!--添加一个二级缓存的供应商(实现类)-->
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property> <!--开启查询缓存-->
<property name="hibernate.cache.use_query_cache">true</property> <!-- 映射文件-->
<mapping resource="mapper/Product.hbm.xml"/> <!--配置那个domain需要二级缓存(最好添加在映射文件后)-->
<class-cache class="com.hibernate.pojo.Product" usage="read-write" />
</session-factory>
</hibernate-configuration>
3、测试二级缓存
/**
* 测试二级缓存
*/
@Test
public void testSecondLevelCache(){
//1.获取session
Session session = HibernateUtil.getSession();
//2.开启事务
Transaction transaction = session.getTransaction();
transaction.begin();
//3.操作CRUD
Product product1 = (Product) session.get(Product.class, 1); //一、二级缓存都没有命中
System.out.println(product1.hashCode());
Product product2 = (Product) session.get(Product.class, 1); //一级缓存命中
System.out.println(product2.hashCode());
session.close(); Session session2 = HibernateUtil.getSession();
Product product3 = (Product) session2.get(Product.class, 1); //二级缓存命中
System.out.println(product3.hashCode());
Product product4 = (Product) session2.get(Product.class, 1); //一级缓存命中
System.out.println(product4.hashCode()); //4.提交事务
transaction.commit();
//5.关闭资源
session2.close();
}
}
控制台输出:
分析:
第一次 get 操作获取到 product1 时,一级,二级缓存都没有,所有发送 SQL 语句查询,并保存到一级缓存和二级缓存中;
第二次 get 操作直接从一级缓存获取数据,所有两个对象的 hashCode 相同;
第三次 get 操作时,由于前一个 session 被关闭了,所有没有一级缓存,只有从二级缓存中获取数据,并保存到新session中;
第四次 get 操作时,直接从 session 的一级缓存中获取数据,hashCode 和 product3 的 hashCode 相同。
Hibernate 学习(三)的更多相关文章
- hibernate学习三(使用Annotation,注解)
一.新建一个工程hibernate_02_HelloWorld_Annotation(复制01工程并重命名); 二.新建一个实体类teacher.java,数据库中新建teacher表; import ...
- hibernate学习(三) hibernate中的对象状态
hibernate对象的状态分为三种: 游离状态,持久化状态,瞬时状态 下面一行代码区分: Configuration cfg=new Configuration().configure(); ...
- Hibernate学习(三)自动建表
一般情况下有如下两种方法: 1.在配置文件中添加如下配置 <property name="hibernate.hbm2ddl.auto">create</prop ...
- Hibernate学习三----------session详解
© 版权声明:本文为博主原创文章,转载请注明出处 如何获取session对象 1. openSession 2. getCurrentSession - 如果使用getCurrentSession需要 ...
- hibernate学习三 精解Hibernate之核心文件
一 hibernate.cfg.xml详解 1 JDBC连接: 2 配置C3P0连接池: 3 配置JNDI数据源: 4 可选的配置属性: 5 hibernate二级缓存属性 6 hibernate事务 ...
- Hibernate学习2--对象的三种状态以及映射关系的简单配置
上篇hibernate的博客总体简单梳理了对象持久化的一些思想以及hibernate中对象持久化化的方法,下面说说对象持久化过程的三种状态. 一.hibernate缓存的概念 1.session与缓存 ...
- Hibernate学习之——搭建log4j日志环境
昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...
- Hibernate学习笔记(二)
2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...
- [原创]java WEB学习笔记88:Hibernate学习之路-- -Hibernate检索策略(立即检索,延迟检索,迫切左外连接检索)
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- [原创]java WEB学习笔记87:Hibernate学习之路-- -映射 继承关系(subclass , joined-subclass,union-subclass )
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- 内置函数和numpy中的min(),max()函数
内置min()函数 numpy中的min()函数:
- mySQL授权(让从服务器用户可以登录到主服务器)
mySQL授权(让从服务器用户可以登录到主服务器) 1.查看用户授权表 ? 1 select user,host,password from mysql.user; 2.给用户设置密码 ? 1 2 u ...
- 通过Nginx部署Django
Django的部署可以有很多方式,采用nginx+uwsgi的方式是其中比较常见的一种方式. 在这种方式中,我们的通常做法是,将nginx作为服务器最前端,它将接收WEB的所有请求,统一管理请求.ng ...
- tableView header Refresh 下拉刷新/上拉加载
一. UIScrollView 的分类 //作为入口 #import <UIKit/UIKit.h> #import "RefreshHeader.h" #import ...
- String字符串补位
String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的读者应该记得C语言的sprintf()方法,两者有类似之处.format()方法有两种重载形式. l ...
- JAVA数据结构--二叉查找树
二叉查找树定义 二叉查找树(英语:Binary Search Tree),也称二叉搜索树.有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted binary tr ...
- Codeforces - 24D 有后效性的DP处理
题意:在n*m的网格中,某个物体初始置于点(x,y),每一步行动都会等概率地停留在原地/往左/往右/往下走,求走到最后一行的的步数的数学期望,其中n,m<1000 lyd告诉我们这种题目要倒推处 ...
- Oracle递归查询(start with…connect by prior)
查询基本结构: select … from table_name start with 条件1 connect by 条件2 1.建测试用表 create table test ...
- 使用chart.js時取消懸浮在圖表頂部的'undefined'標識
解決方法:在options中設置legend項中display屬性為false options: { scales: { yAxes: [{ ticks: { beginAtZero: true } ...
- 网络编程- 解决黏包现象方案二之struct模块(七)
上面利用struct模块与方案一比较,减少一次发送和接收请求,因为方案一无法知道client端发送内容的长度到底有多长需要和接收OK.多一次请求防止黏包,减少网络延迟