Hibernate技术
Hibernate中3个重要的类:
配置类(configuration)
负责管理Hibernate的配置信息,包含数据库连接URL、数据库用户、数据库密麻麻、数据库驱动等。
会话工厂类(SessionFactory)
保存当前数据库所有映射关系。
会话类(Session)
对数据库的操作,实现数据库数据增、删、改、查。该类不是 线程安全。 Hibernate配置文件
配置文件数据库链接的文件有两:Hibernate.properties或Hibernate.cfg.xml
Hibernate.properties文件内容
#数据库驱动
hibernate.connection.driver_class = oracle.jdbc.driver.OracleDriver
#数据库连接的URL
hibernate.connection.url = jdbc:oracle:thin:@127.0.0.1:1521:orcl
#用户名
hibernate.connection.username = system
#密码
hibernate.connection.password = guoyanan
#是否显示SQL语句
hibernate.show_sql=true
#是否自动生存数据表
#hibernate.hbm2ddl.auto=true
#是否格式化SQL
hibernate.format_sql=true
#Hibernate方言
hibernate.dialect = org.hibernate.dialect.OracleDialect
Hibernate.cfg.xml文件内容
<!-- 数据库驱动 -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<!-- URL -->
<property name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:orcl</property>
<!-- 数据库登录帐号 -->
<property name="connection.username">system</property>
<!-- 数据库登录密码 -->
<property name="connection.password">guoyanan</property>
<!-- 数据库方言 -->
<property name="dialect">org.hibernate.dialect.OracleDialect</property>
数据库方言不同的数据库是不一样的
数据库 方言
Oracle(通用的) org.hibernate.dialect.OracleDialect
SQLServer org.hibernate.dialect.SQLServerDialect
MySQL org.hibernate.dialect.MySQLDialect 编写持久化类
public class Tb_User {
private int id;
private String username;
private String password; //无参构造函数
public Tb_User(){ }
public int getId() {
return id;
} public void setId(int id) {
this.id = id;
}
…
} 持久化类必须符合PoJO规范。
Hibernate持久化类中必须符合4条规则:
1、 必须实现一个无参的构造函数,方便Hibernate通过Constructor.nerInstance实例持久化。
2、 提供一个标识属性,就是数据库表中的主键。
3、 使用非final类,如果使用了final类,Hibernate不能使用代理延迟加载。
4、 为属性声明访问器,也就是创建公共的set和get方法。 Hibernate映射文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- 员工信息字段配置信息 -->
<hibernate-mapping>
<class name="com.hibernate.table.Tb_User" table="tb_user">
<!-- id值 -->
<id name="id" column="id" type="int">
<generator class="native"/>
</id>
<!-- 帐号 -->
<property name="username" type="string" length="20">
<column name="username"/>
</property>
<!-- 密码 -->
<property name="password" type="string" lenght=20>
<column name="password"></column>
</property>
</class>
</hibernate-mapping> <property>元素常用的属性
属性名称 说明
Name 持久化类属性的名称,以小写字母开头
Column 数据库字段名称
Type 数据库字段类型
Length 数据库字段长度
Not-null 设置字段是否可以为空,bool类型
Unique 字段是否唯一,bool类型
Lazy 是否延迟抓取,bool类型 Hibernate主键策略
<generator>元素是java类名设置主键的策略。
属性名称 说明
increment 用于为long、short或int类型生成唯一标识,在集群下不可以使用
indentity 由底层数据库生存主键
sequence 有底层序列生存主键
hilo 根据高/低算法生存,把特定表的字段作为高位值来源,在默认情况下选用hibernate_unique_key表的next_hi字段
native 根据底层数据库对自动生成标识符的支持能力选择identity、sequence、hilo。
assigned 由程序负责主键生存,此时持久化类的唯一标识不能声明为private类型
select 通过数据库触发生存主键
foreign 使用另一个相关的对象的标识符,通常和<one-to-one>一起使用 Hibernate的Generator属性有7种class,本文简略描述了这7种class的意义和用法。
1、identity:用于MySql数据库。特点:递增
1. < id name="id" column="id">
2. < generator class="identity"/>
3. < /id>
注:对于MySql数据库使用递增序列时需要在建表时对主键指定为auto_increment属性。
2、sequence:用于Oracle数据库
1. < id name="id" column="id">
2. < generator class="sequence">
3. < param name="sequence">序列名< /param>
4. < /generator>
5. < /id>
3、native:跨数据库时使用,由底层方言产生。
Default.sequence为hibernate_sequence
1. < id name="id" column="id">
2. < generator class="native"/>
3. < /id>
注:使用native时Hibernate默认会去查找Oracle中的hibernate_sequence序列。
如果Oracle中没有该序列,连Oracle数据库时会报错。
4、hilo:通过高低位合成id,先建表hi_value,再建列next_value。必须要有初始值。
1. < id name="id" column="id">
2. < generator class="hilo">
3. < param name="table">high_val< /param>
4. < param name="column">nextval< /param>
5. < param name="max_lo">5< /param>
6. < /generator>
7. < /id>
5、sequencehilo:同过高低位合成id,建一个sequence序列,不用建表。
1. < id name="id" column="id">
2. < generator class="hilo">
3. < param name="sequence">high_val_seq< /param>
4. < param name="max_lo">5< /param>
5. < /generator>
6. < /id>
6、assigned:用户自定义id;
1. < id name="id" column="id">
2. < generator class="assigned"/>
3. < /id>
7、foreign:用于一对一关系共享主健时,两id值一样。 Hibernate实例状态
1、 瞬时状态(transient)
通过new关键字创建的java对象,没有被Hibernate Session管理,当没有变量引用是就有JVM自动回收。
2、 持久化状态(Persistent)
对象与数据库中的数据关联,并与Session会话和Transaction事务关联在一起,当持久化状态对象发生改变时并不会立即更新数据库,只有当事务结束时,才会更新数据库。当持久化状态变为脱管状态后,就不在Hibernate持久化成管理范围内。
3、 脱管状态(Detached)
当持久化对象的Session关闭后,对象就进入了脱管状态。当脱管对象,有被Session重新管理,就进入到了持久化状态。 Hibernate持久类
package ssh.gx; import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistryBuilder; public class HibernateUtil {
private static final ThreadLocal<Session> threadLocal = new ThreadLocal <Session>();
private static SessionFactory sessionFactory = null; //SessionFactory对象
//静态块
static {
try {
Configuration cfg = new Configuration().configure(); //加载Hibernate配置文件
sessionFactory = cfg.buildSessionFactory(new ServiceRegistryBuilder().buildServiceRegistry());
} catch (Exception e) {
System.err.println("创建会话工厂失败");
e.printStackTrace();
}
}
/**
* 获取Session
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession(): null;
threadLocal.set(session);
}
return session;
}
/**
* 重建会话工厂
*/
public static void rebuildSessionFactory() {
try {
Configuration cfg = new Configuration().configure(); //加载Hibernate配置文件
sessionFactory = cfg.buildSessionFactory(new ServiceRegistryBuilder().buildServiceRegistry());
} catch (Exception e) {
System.err.println("创建会话工厂失败");
e.printStackTrace();
}
}
/**
* 获取SessionFactory对象
* @return SessionFactory对象
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* 关闭Session
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close(); //关闭Session
}
}
} SessionFactory是重量级的对象,创建需要耗费大量的资源,所以,在static块中创建,程序运行过程中就只创建一次。 添加数据
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub //声明Session
Session session=null;
//设置内容类型,防止中文乱码
response.setContentType("text/html;charset=utf-8"); //实例化Tb_User类
Tb_User user=new Tb_User();
//添加数据信息
user.setUsername("xiaoming");
user.setPassword("123xiao"); //Hibernate持久化
try{
//获取session
session=HibernateUtil.getSession();
//开启事务
session.beginTransaction();
//执行数据操作
session.save(user);
//事务提交
session.getTransaction().commit(); //获取out对象
PrintWriter out =response.getWriter();
out.println("<script>alert('ok');</script>"); }catch(Exception e){
System.out.println("数据持久化失败");
e.printStackTrace();
}
doGet(request, response);
} 查询数据
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//声明Session
Session session=null;
//防止中文乱码
response.setContentType("text/html;charset=utf-8");
try{
//获取session
session=HibernateUtil.getSession();
//装载对象
Tb_User user=(Tb_User)session.get(Tb_User.class, new Integer("6")); //输出查询结果
System.out.println(user.getId());
System.out.println(user.getUsername());
System.out.println(user.getPassword()); }catch(Exception e){
System.out.println("查询对象失败");
e.printStackTrace();
} doGet(request, response);
} 修改或删除数据
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//声明session
Session session=null;
//设置响应头信息,防止中文乱码
response.setContentType("text/html;charset=utf-8"); try{
//获取session对象
session=HibernateUtil.getSession();
//装载对象
Tb_User user=(Tb_User)session.get(Tb_User.class, new Integer("6")); //修改对象部分
user.setUsername("小明");
user.setPassword("ewq123");
//强制刷新提交
session.flush();
//提交事务
session.getTransaction().commit(); /*
//对象删除
session.delete(user);
//强制刷新提交
session.flush();
//提交事务
session.getTransaction().commit();
*/ }catch(Exception e){
System.out.println("失败");
e.printStackTrace();
} doGet(request, response);
} 延迟加载
Hibernate调用代理的某个方法来访问数据库。非延迟加载,Hibernate直接访问数据库。
延迟加载的策略
当被加载的对象,长时间没有被调用,JVM(垃圾回收器)自动回收资源。 配置和使用二级缓存
Hibernate的二级缓存由从属于一个SessionFactory的所有Session对象共享,当程序使用Session加载持久化对象时,Session首先会根据加载的数据类和唯一标识在缓存中查找是否存在此对象的缓存实例。如果存在,将其作为结果返回;否则继续在二级缓存中查找。如果无匹配对象,Hibernate将直接访问数据库。
Hibernate.cfg.xml配置开启二级缓存
<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 指定缓存产品提供商 -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> 持久化类的映射文件指定缓存的同步策略:
<hibernate-mapping>
<class name="com.hibernate.table.Tb_User" table="tb_user">
<!-- 指定的缓存的同步策略 -->
<cache usage="read-only"></cache>
… 添加缓存配置文件ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<!-- maxElementsInMemory缓存允许保存的最大数据库实例量;
eternal缓存中的数据是否为常量;timeToIdleSeconds缓存钝化时间;
timeToLiveSeconds缓存数据生存时间;overflowToDisk设置是否启用磁盘缓存。 -->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache> Servlet测试二级缓存
Session session=null;
Session session2=null;
//防止中文乱码
response.setContentType("text/html;charset=utf-8");
try{
//获取session
session=HibernateUtil.getSession();
session2=HibernateUtil.getSession();
//装载对象
Tb_User user=(Tb_User)session.get(Tb_User.class, new Integer("6"));
Tb_User user2=(Tb_User)session2.get(Tb_User.class, new Integer("6"));
//输出查询结果
System.out.println(user.getId());
System.out.println(user.getUsername());
System.out.println(user.getPassword()); }catch(Exception e){
System.out.println("查询对象失败");
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
} 在输出控制台输出:可以看到,程序只执行了一次sql语句。第二次session2执行查询的是二级缓存。
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Hibernate:
select
tb_user0_.id as id0_0_,
tb_user0_.username as username0_0_,
tb_user0_.password as password0_0_
from
tb_user tb_user0_
where
tb_user0_.id=?
6
xiaoming
123xiao 二级缓存是常用与数据更新频率低且系统频繁使用的非关键数据,以防止用户频繁访问数据库而过度消耗系统资源。 实体关联关系映射
实体类的关系属性必须以关联类声明。
private Tb_User userid;
xml属性
<!-- 银行卡号与用户多对一关系 -->
<many-to-one name="userid" class="com.hibernate.table.Tb_User">
<column name="userid"></column>
</many-to-one> Servlet使用
//声明Session
Session session=null; //防止中文乱码
response.setContentType("text/html;charset=utf-8");
try{
//获取session
session=HibernateUtil.getSession(); //装载对象
Tb_Card card=(Tb_Card)session.get(Tb_Card.class, new Integer("999")); //输出查询结果
System.out.println(card.getCardid());
System.out.println(card.getUserid().getBankcard());
}catch(Exception e){
System.out.println("查询对象失败");
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
} 配置多对一的双向关联
持久类里添加如下代码
public class Tb_User {
private int id;
private String username;
private String password;
private String bankcard;
private Set<Tb_Card> tbcard;
…省略set和get 配置文件内容
<!-- 定义一对多 inverse属性用于控制反向反转 -->
<set name="tbcard" inverse="true">
<!-- 设置多对一的实体字段 -->
<key column="userid"></key>
<one-to-many class="com.hibernate.table.Tb_Card"/>
</set> Servlet执行代码
//声明Session
Session session=null; //防止中文乱码
response.setContentType("text/html;charset=utf-8");
try{
//获取session
session=HibernateUtil.getSession();
//装载对象
Tb_User user=(Tb_User)session.get(Tb_User.class, new Integer("6"));
//输出查询结果
System.out.println(user.getUsername());
//获取Tb_Card的集合
Set<Tb_Card> cards=user.getTbcard();
//通过迭代器输出信息
for(Iterator<Tb_Card> it=cards.iterator();it.hasNext();){
//获取产品信息
Tb_Card card=(Tb_Card)it.next();
//输出信息
System.out.println(card.getCardid());
}
}catch(Exception e){
System.out.println("查询对象失败");
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
} 配置一对一的主键关联 主控实体类
public class Tb_User {
private int id;
private String username;
private String password;
private String bankcard;
//数据库对应的表中并没有cardnoid字段,此字段为实体类需要实现一对一关系而添加
private tbCardNo cardnoid;
…省略set和get方法 被控实体类
public class tbCardNo {
private int id;
private String CardNo;
…省略set和get 主控配置文件
<!-- 一对一的属性 cascade级联操作属性-->
<one-to-one name="cardnoid" class="com.hibernate.table.tbCardNo" cascade="delete"></one-to-one> 被控配置文件
<hibernate-mapping>
<class name="com.hibernate.table.tbCardNo" table="tb_CardNo">
<id name="id" column="id" type="int">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
… 执行代码
//声明Session
Session session=null; //防止中文乱码
response.setContentType("text/html;charset=utf-8");
try{
//获取session
session=HibernateUtil.getSession();
session.beginTransaction();
//装载对象
Tb_User user=(Tb_User)session.get(Tb_User.class, new Integer("7")); session.delete(user);
session.getTransaction().commit(); }catch(Exception e){
System.out.println("查询对象失败");
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
} 级联操作
主要是由cascade属性控制,cascade属性属于关系标签<one-to-one>、<many-to-one>、<one-to-many>。
参数 说明
All 所以情况下均采用级联操作
None 默认,所有情况下均不采用级联操作
Save-update 在执行save-update方法时执行级联操作
Delete 在执行delete方法时执行级联操作 HQL语句
HQL语句与SQL语句是十分相似的。一般的Sql语句可以执行的都可以使用HQL语句实现查询。
区别:HQL是通过实体查询,SQL是在数据库里查询表。
HQL语句可以通过from子句查询实体。
From Tb_User; HQL语句查询实例
//声明Session
Session session=null; //防止中文乱码
response.setContentType("text/html;charset=utf-8");
try{
//获取session
session=HibernateUtil.getSession();
//编辑Hql查询语句
String hql="select user.id,user.username,user.password from Tb_User user where user.username=? and user.password=:password";
//使用sql语句查询
String sql="select t.id,t.username,t.password from tb_user t where t.username=? and t.password=:password";
Query q=session.createQuery(hql);
//使用sql语句查询
Query sq=session.createSQLQuery(sql); //使用站位符“?”替代参数
q.setParameter(0, "qwe");
//使用站位符“:parameter”替代变量
q.setParameter("password", "123"); //使用站位符“?”替代参数
sq.setParameter(0, "qwe");
//使用站位符“:parameter”替代变量
sq.setParameter("password", "123");
//查询的是一个实体对象,也就是如Tb_User可以使用以下代码
List<Tb_User> list=new ArrayList<Tb_User>();
//查询多个实体对象时使用以下代码,使用Object对象数组
List<Object[]> lists=new ArrayList<Object[]>(); //lists=sq.list();使用sql查询获取list结果
lists=q.list();
//使用迭代器
Iterator it =lists.iterator();
while(it.hasNext()){
Object[] oj=(Object[])it.next(); System.out.println(oj[].toString());
System.out.println(oj[].toString());
System.out.println(oj[].toString()); } }catch(Exception e){
System.out.println("查询对象失败");
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
} Hql语句可以使用排序查询、聚会函数查询、分组查询、联合查询与SQL语句使用是一样的,就不介绍了。
通过Hibernate执行sql语句查询,只需要将上面的代码里session.createQuery(hql)替换为session.createSQLQuery(sql)。
Hibernate技术的更多相关文章
- Hibernate技术入门
ORM原理 ORM(Object Relational Mapping)是对象到关系的映射,它的作用是在关系数据库和对象之间做一个自动映射,将数据库中的数据表映射成对象(持久化类),对关系型数据库以对 ...
- Hibernate与jsp技术结合的小例子
今天在某个教程上看到了jsp技术与Hibernate技术结合的一个小的例子,觉得很好,把它实现出来 按照Hibernate建工程的一贯做法, 首先 我们建立一个Hibernate工程,在工程下添加我们 ...
- hibernate理解
SSH框架: Struts框架, 基于mvc模式的应用层框架技术! Hibernate,基于持久层的框架(数据访问层使用)! Spring,创建对象处理对象的依赖关系以及框架整合! Dao代码,如何编 ...
- [Java面试八]Hibernate总结以及在面试中的一些问题.
1.为什么要使用Hibernate开发你的项目呢?Hibernate的开发流程是怎么样的? 为什么要使用 ①.对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码. ②.Hiber ...
- Java Web整合开发实战:基于Struts 2+Hibernate+Spring 目录
第1篇 Java Web开发基础第1章 Web的工作机制( 教学视频:31分钟) 1.1 理解Web的概念 1.1.1 Web的定义 1.1.2 Web的三个核心标准 1.2 C/S与B/S两种软件体 ...
- 使用MyEclipse可视化开发Hibernate实例
2.7 使用MyEclipse可视化开发Hibernate实例 2.7节的例子源代码在配套光盘sourcecode/workspace目录的chapter02_first项目中. 这个实例主要演示如 ...
- 初识hibernate
//针对myEclipse2014版本 怎样新建一个工程实现这些东西的导入. 打开myeclipse. 2.点击右上角的open perspective 找到这个 MyEclipse Database ...
- JDBC、Hibernate、Mybaites处理数据的流程及对DAO的理解
以查询一个用户信息(id,name)为例: JDBC 1. 获取一个connection 2. 生成一个statement 3. 拼接SQL语句 4. 查询对象,获取结果集(假设已经找到我们需要的对象 ...
- Hibernate框架--配置,映射,主键
SSH框架: Struts框架, 基于mvc模式的应用层框架技术! Hibernate, 基于持久层的框架(数据访问层使用)! Spring, 创建对象处理对象的依赖关系以及框架整合! Da ...
随机推荐
- 浅谈"壳"(一)
壳,即坚硬的外皮,当壳的厚度与其曲面率半径的比值小于0.5时.称为"薄壳".反之称为"厚壳".由壳演化来的胸甲,盾牌. 在计算机这个注重创意又不失从文化科技中汲 ...
- 题目1 : Farthest Point
时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 Given a circle on a two-dimentional plane. Output the integral ...
- #define的使用方法体会
#define 创建一个宏,该宏是标识符或參数化标识符与标记字符串的关联. 在定义宏之后.编译器可用标记字符串替换源文件里标识符的每一个匹配项. 双击以所有折叠.">语法 #defin ...
- Android 下拉刷新上拉载入 多种应用场景 超级大放送(上)
转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/47707017 关于Android下拉刷新上拉载入,网上的Demo太多太多了,这 ...
- Lumen开发:lumen源码解读之初始化(5)——注册(register)与启动(boot)
版权声明:本文为博主原创文章,未经博主允许不得转载. register()是在服务容器注册服务, bootstrap/app.php /** * 注册外部服务 */ $app->register ...
- 做完task1-21的阶段总结
[说明]这是自注册修真院的第七天,也是第七篇日报,觉得是一个好的时机总结一下. 因为任务一虽然看起来仅仅是“完成学员报名的DB设计并读写数据库”,但是做了几天之后就发现在任务“搭建自己的服务器”之前的 ...
- 【BZOJ5016】[Snoi2017]一个简单的询问 莫队
[BZOJ5016][Snoi2017]一个简单的询问 Description 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计 ...
- RedisTemplate访问Redis数据结构(介绍和常用命令)
Redis 数据结构简介 Redis 可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串).List(列表).Set(集合).Hash(散列)和 Zset(有序集 ...
- java服务安装(一):使用java service wrapper及maven打zip包
目录(?)[+] 1概述 1_1为什么要用服务形式运行 1_2如何让java程序以服务形式运行 1_3打包需求 2程序示例 3maven打zip包 3_1maven-assembly-plugin介绍 ...
- 九度OJ 1350:二叉树的深度 (二叉树)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1044 解决:614 题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长 ...