hibernate框架总结
实体类编写规则
1 实体类里面属性私有的
2 私有属性使用公开的set和get方法操作
3 要求实体类有属性作为唯一值(一般使用id值)
4 实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装类
(1)八个基本数据类型对应的包装类
- int – Integer
- char—Character、
- 其他的都是首字母大写 比如 double – Double
(2)比如 表示学生的分数,假如 int score;
- 比如学生得了0分 ,int score = 0;
- 如果表示学生没有参加考试,int score = 0;不能准确表示学生是否参加考试
解决:使用包装类可以了, Integer score = 0,表示学生得了0分,
表示学生没有参加考试,Integer score = null;
对实体类crud操作
添加操作
1 调用session里面的save方法实现
根据id查询
1 调用session里面的get方法实现
修改操作
1 首先查询,然后修改值
(1)根据id查询,返回对象
删除操作
1 调用session里面delete方法实现
实体类对象状态(概念)
1 实体类状态有三种
(1)瞬时态:对象里面没有id值,对象与session没有关联
(2)持久态:对象里面有id值,对象与session关联
(3)托管态:对象有id值,对象与session没有关联
2 演示操作实体类对象的方法
(1)saveOrUpdate方法:实现添加、实现修改
测试代码:
一.创建瞬时态对象[没有id,与session没有关联],使用saveOrupdate保存,做插入操作
Customer c=new Customer();
c.setCname("传智");
session.saveOrUpdate(c);
底层sql语句
Hibernate:
insert
into
t_customer
(cname, tel)
values
(?, ?)
数据库插入了一条数据(使用的是主键自动增长策略):
二.创建托管态对象[有id,与session没有关联],使用saveOrupdate保存,做更新操作
首先需要明白它做的是更新的操作,那么问题就产生了,如果数据库中存在这个id值,那么会更新,
如果设置的id值,数据库中没有呢?那么就无法完成更细,会报错
(1)数据库中没有该id值(数据库中没有id为9的记录,那么进行更新的时候肯定会报错)
Customer c=new Customer();
c.setCid(9);
c.setCname("传智9");
session.saveOrUpdate(c);
(2)数据库中有该id值(把id为1的记录的cname字段由“传智播客1”改为“百度”)
Customer c=new Customer();
c.setCid(1);
c.setCname("百度");
session.saveOrUpdate(c);
底层sql
Hibernate:
update
t_customer
set
cname=?,
tel=?
where
cid=?
Hibernate:
update
t_linkman
set
clid=null
where
clid=?
数据库是更新了没错
但是它又多了一条更新语句,就是把关联表中的外键字段置为null,首先这里只需要明白产生的原因是hibernate双向维护机制,解决办法就是在customer配置文件的set标签中使用
inverse="true" 表示让它放弃外键的维护能力,这样就不会出现下面的更新语句了,详解请参考框架截图总结(一)
当然上面演示的情况因为在关联表中本来就没有记录,所以没有影响,但是如果是存在记录,那么根据打印的sql语句就能知道一定会出现下面的情况
修改之前数据库中的记录(存在外键的约束,即百度这个客户它对应的联系人是李彦宏):
现在把百度的名称,改变为百度1
Customer c=new Customer();
c.setCid(1);
c.setCname("百度1");
session.saveOrUpdate(c);
sql语句:
Hibernate:
update
t_customer
set
cname=?,
tel=?
where
cid=?
Hibernate:
update
t_linkman
set
clid=null
where
clid=?
所以看表中的变化
更新没有问题,但是联系人表中的外键字段是null
三.创建持久态对象[有id,与session有关联],使用saveOrupdate保存,做更新操作
修改之前
现在把百度1改回百度
Customer c=session.get(Customer.class,1);//持久态对象
c.setCid(1);//这条语句写不写对结果没有任何的影响,因为id的值没有变化,但是如果把id值改变就会保错
c.setCname("百度");
session.saveOrUpdate(c);
sql语句:
Hibernate:
select
customer0_.cid as cid1_0_0_,
customer0_.cname as cname2_0_0_,
customer0_.tel as tel3_0_0_
from
t_customer customer0_
where
customer0_.cid=?
Hibernate:
update
t_customer
set
cname=?,
tel=?
where
cid=?
只做一次更新,观察数据库中的变化
可以发现在修改持久态对象的时候,并没有把关联表的外键字段置为null的语句打印,说明托管态和持久态之间使用saveOrupdate是有区别的虽然同样是更新操作,托管态在
更新数据之后会把关联表的外键字段再做一次更新(做了2次更新),置为null,而持久态的对象在更新之后只是更新了自己表的数据(1次更新)
全部测试代码:
package org.testdemo; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import org.model.User;
import org.util.SessionFactoryUtil; public class TestDemo {
// 1通过工具类得到sessionfactory 对象
// SessionFactory sessionfactory = SessionFactoryUtil.getSessionFactory();
// 2通过sessionfactory得到session对象
// Session session = sessionfactory.openSession();
// 3通过session创建事务
// Transaction tran = session.beginTransaction(); // 4进行数据库的操作 // 5提交事务
// tran.commit();
// 6关闭链接
// session.close();
// sessionfactory.close(); @Test
public void add() {
//insert into t_user(name,password) values(?,?)
SessionFactory sessionfactory = SessionFactoryUtil.getSessionFactory();
Session session = sessionfactory.openSession();
Transaction tran = session.beginTransaction();
//添加一条数据
User user = new User();
user.setName("jay");
user.setPassword("root");
session.save(user);
tran.commit();
session.close();
sessionfactory.close(); } @Test
public void select() {
//select * from t_user where id=?
SessionFactory sessionfactory = SessionFactoryUtil.getSessionFactory();
Session session = sessionfactory.openSession();
Transaction tran = session.beginTransaction();
//查询一条记录 根据id值
User user = session.get(User.class, 1);
System.out.println(user);
tran.commit();
session.close();
sessionfactory.close();
} @Test
public void update() {
//update t_user set name=?,password=? where id=?
SessionFactory sessionfactory = SessionFactoryUtil.getSessionFactory();
Session session = sessionfactory.openSession();
Transaction tran = session.beginTransaction();
//执行修改操作 先找到对象 在进行修改 最后使用update方法执行最后的变更
User user=session.get(User.class,1);
user.setName("Joke");
session.update(user); tran.commit();
session.close();
sessionfactory.close();
} @Test
public void delete() {
//delete from t_user where id=?
SessionFactory sessionfactory = SessionFactoryUtil.getSessionFactory();
Session session = sessionfactory.openSession();
Transaction tran = session.beginTransaction();
//执行删除操作 先找到对象 在进行删除
User user=session.get(User.class,1);
session.delete(user);
// User user=new User();
// user.setUid(2);
// session.delete(user); tran.commit();
session.close();
sessionfactory.close();
} @Test
public void saveorupdate() {
//delete from t_user where id=?
SessionFactory sessionfactory = SessionFactoryUtil.getSessionFactory();
Session session = sessionfactory.openSession();
Transaction tran = session.beginTransaction(); //创建游离态
// User user=new User();
// user.setName("aa");
// user.setPassword("bb");
// session.saveOrUpdate(user);//执行插入操作 //创建托管态
// User user=new User();
// user.setUid(3);
// user.setName("cc2");
// user.setPassword("dd3");
// session.saveOrUpdate(user);//执行更新操作 //创建持久态
User user=session.get(User.class,3);
user.setName("feafw");
session.saveOrUpdate(user);//执行更新操作 tran.commit();
session.close();
sessionfactory.close();
} }
Hibernate的一级缓存
什么是缓存
1 数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很高。
(1)把数据存到内存里面,不需要使用流方式,可以直接读取内存中数据
(2)把数据放到内存中,提供读取效率
Hibernate缓存
1 hibernate框架中提供很多优化方式,hibernate的缓存就是一个优化方式
2 hibernate缓存特点:
第一类 hibernate的一级缓存
(1)hibernate的一级缓存默认打开的
(2)hibernate的一级缓存使用范围,是session范围,从session创建到session关闭范围
(3)hibernate的一级缓存中,存储数据必须 持久态数据
第二类 hibernate的二级缓存
(1)目前已经不使用了,替代技术 redis
(2)二级缓存默认不是打开的,需要配置
(3)二级缓存使用范围,是sessionFactory范围
验证一级缓存存在
1 验证方式
(1)首先根据uid=1查询,返回对象
(2)其次再根据uid=1查询,返回对象
第一步执行get方法之后,发送sql语句查询数据库
第二个执行get方法之后,没有发送sql语句,查询一级缓存内容
Hibernate一级缓存执行过程
注意一级缓存中保存的数据并不是一个对象,而是每个对象的属性的值
Hibernate一级缓存特性
1 持久态自动更新数据库
@Test
public void testauto(){
SessionFactory sessionfactory=SessionFactoryUtil.getSessionFactory();
Session session=sessionfactory.openSession();
Transaction tran=session.beginTransaction();
//得到持久态对象
User user=session.get(User.class,3);
//修改持久态对象
user.setName("jay");
//这里不需要保存 因为是持久态 所以会自动进行更新数据库
tran.commit();
session.close();
sessionfactory.close();
}
代码执行到第7行的时候,控制台打印出查询语句,之后事务进行提交的时候,自动更新了数据库
需要注意的是:
如果修改前和修改时的数据一样,那么缓存机制并不会做更新操作 比如上面的代码在重新执行一次
执行后控制台打印的结果
因为数据没有发生变化,所以并没有执行更新
原因:观察下面这张图:
当执行get方法的时候,如果一级缓存中没有所需要的数据,就进行数据库的查询操作,把得到的数据保存在以及缓存的同时,还复制一份保存在快照区中,进行set方法更新的时候 只是修改一级缓存中的数据,并不修改快照区中的内容,当进行事务提交的时候,对比快照区和一级缓存中的数据是否一样,不一样则更新数据库以及把修改之后的内容存在以及缓存和快照区中, 一样则不做任何的更新操作
Hibernate事务代码规范写法
@Test
public void testTx() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction(); //添加
User user = new User();
user.setUsername("小马");
user.setPassword("250");
user.setAddress("美国"); session.save(user); int i = 10/0;
//提交事务
tx.commit();
}catch(Exception e) {
e.printStackTrace();
//回滚事务
tx.rollback();
}finally {
//关闭操作
session.close();
sessionFactory.close();
}
}
Hibernate绑定session
hibernate中的session对象可以看做是一个与数据库的链接,它的特点是单线程对象(只能自己用,别人不能用,每个用户都有一个自己的session对象)
为了保证它绝对是一个单线程对象,可以把session与本地线程进行绑定
1 session类似于jdbc的connection,之前web阶段学过 ThreadLocal,绑定session底层的原理就是 ThreadLocal
2框架 帮实现与本地线程绑定session
3 获取与本地线程session
(1)在hibernate核心配置文件中配置
(2)使用sessionfactory.getCurrentSession()方法得到与本地线程绑定的session
(一般在工具类中提供一个方法,返回这个session)
代码实践:
<?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-configuration>
<session-factory>
<!-- 配置数据库 信息 必须的 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">jay571018</property>
<property name="hibernate.connection.url">jdbc:mysql:///Hibernate2_demo1</property> <!-- 2. 配置hibernate信息 可选的 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property> <!-- 配置本地线程 绑定session -->
<property name="hibernate.current_session_context_class">thread</property> <!-- 3 配置对象关系映射文件的位置 -->
<mapping resource="org/model/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
package org.util; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; public class SessionFactoryUtil {
private static Configuration configuratrion=null;
private static SessionFactory sessionfactory=null;
static{//静态代码块 只会在类加载的时候执行一次 创建一次sessionfactory对象 提高性能
configuratrion=new Configuration();
configuratrion.configure();//加载配置文件
sessionfactory=configuratrion.buildSessionFactory();
}
//创建一个方法返回sessionfactory对象
public static SessionFactory getSessionFactory(){
return sessionfactory;
}
//提供返回 与本地线程绑定的session的方法
public static Session get(){
return sessionfactory.getCurrentSession();
} public static void close(){
sessionfactory.close();
}
public static void main(String args[]){ }
}
这样在使用session的时候可以通过这个方法直接得到session对象,并且是与本地线程绑定的,保证是单线程对象
但是注意 :不需要我们手动关闭session了
public void t(){
Session session=SessionFactoryUtil.get();
Transaction tran=session.beginTransaction();
User u=new User();
u.setName("a");
u.setPassword("a");
session.save(u);
tran.commit();
session.close();//这里不需要关闭session
}
执行之后 控制台打印:
插入了一条记录,但是出现错误
原因:操作结束的时候,这个线程就结束了,那么session是与本地线程绑定的,自然就结束了,所以不需要在关闭了
如果在dao操作中,使用hibernate提供的模板类HibernateTemplate进行数据操作(不用得到session对象),那么就不需要
在hibernate.cfg.xml中配置<property name="hibernate.current_session_context_class">thread</property>
因为该模板底层实现就是对 与本地线程绑定的session 进行了封装 使用该模板操作数据 就是使用与本地线程绑定的session操作数据
HibernateAPI
Query对象
1 使用query对象,不需要写sql语句,但是写hql语句
(1)hql:hibernate query language,hibernate提供查询语言,这个hql语句和普通sql语句很相似
(2)hql和sql语句区别:
- 使用sql操作表和表字段
- 使用hql操作的是实体类和属性
2 查询所有hql语句:
(1)from 实体类名称
3 Query对象使用
(1)创建Query对象
(2)调用query对象里面的方法得到结果
Criteria对象
1 使用这个对象查询操作,但是使用这个对象时候,不需要写语句
2 实现过程
(1)创建criteria对象
(2)调用对象里面的方法得到结果
SQLQuery对象
里边是写的是sql语句
返回的list集合 每部分是数组的形式
使用方法,使list中每部分是对象形式
sqlQuery.addEntity(实体类);
这样返回的list集合中,每部分就是一个对象了
hibernate框架总结的更多相关文章
- Hibernate框架之Criteria查询 和注解(重点☆☆☆☆☆,难点☆☆☆)
写好一篇博客,不是容易的事.原因是:你要给自己以后看的时候,还能看懂,最重要的是当别人看到你的博客文章的时候,也一样很清楚的明白你自己写的东西.其实这也是一种成就感!! 对于每一个知识点,要有必要的解 ...
- Hibernate 系列 01 - 框架技术 (介绍Hibernate框架的发展由来)
引导目录: Hibernate 系列教程 目录 本篇导航: 为什么学习框架技术 框架的概念 主流框架的介绍 1.为什么学习框架技术 如何制作一份看上去具有专业水准的PPT文档呢?一个简单的方法就是使用 ...
- 2.0、Hibernate框架的简单搭建
一.Hibernate:是一个开放源代码的对象关系映射框架,对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句 ...
- 【Hibernate框架】对象的三种持久化状态
一.综述 hibernate中的对象有三种状态,分别是TransientObjects(瞬时对象).PersistentObjects(持久化对象)和DetachedObjects(托管对象也叫做离线 ...
- hibernate框架int和Integer类型区别
hibernate 框架在定义实体时,int类型最好定义为Inttger类型,因为在注入时int是值类型不允许为空.
- SSH(Struts2+Spring+Hibernate)框架搭建流程<注解的方式创建Bean>
此篇讲的是MyEclipse9工具提供的支持搭建自加包有代码也是相同:用户登录与注册的例子,表字段只有name,password. SSH,xml方式搭建文章链接地址:http://www.cnblo ...
- ECLIPSE/JAVAWEB (二)三大框架之Hibernate框架 持续更新中...
(一)发展历史 在Struts框架中使用jdbc连接来读写数据库,我们最常见的就是打开数据库连接.使用复杂的sql语句进行读写.关闭连接,获得的数据又需要转换或封装后往外传,这是一个非常繁琐的过程. ...
- Hibernate框架简单应用
Hibernate框架简单应用 Hibernate的核心组件在基于MVC设计模式的JAVA WEB应用中,Hibernate可以作为模型层/数据访问层.它通过配置文件(hibernate.proper ...
- Hibernate框架(未完待续······)
作为SSH三大框架之一的Hibernate,是用来把程序的Dao层和数据库打交道用的,它封装了JDBC的步骤,是我们对数据库的操作更加简单,更加快捷.利用Hibernate框架我们就可以不再编 ...
- Hibernate框架之get和load方法的区别
我们在学习Hibernate框架时,经常会进行修改,删除操作,对于这些操作,我们都应该先加载对象,然后在执行或删除的操作,那么这里Hibernate提供了两种方法按照主键加载对象,也就是我要说的get ...
随机推荐
- FPGA 浮点单元设计
浮点数在内存中的存放格式例如以下: 地址 +0 +1 +2 +3 内容 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM 这里 S 代表符号位,1是负,0是正 E 偏移1 ...
- 转:APP测试总结
- Git与SVN区别 \git学习
http://blog.csdn.net/w13770269691/article/details/38705473/ https://git-scm.com/book/zh/v2
- bootstrap模态框通过传值解决重复提交问题
自己通过模态框确认是否提交的功能时,总是重复提价上次的请求. 原因:重复的原因是jquery通过id绑定了确定按钮的onclick事件,所以每次提交都会增加 一次绑定(没有清除上次的绑定),才造成了重 ...
- kali 下使用 arpspoof 实现 ARP 欺骗
ARP 欺骗: 一种中间人攻击,攻击者通过毒化受害者的 ARP 缓存,将网关的 MAC 替换成攻击者的 MAC ,于是攻击者的主机实际上就充当了受害主机的网关, 之后攻击者就可以截获受害者发出和接到的 ...
- Hadoop MapReduce编程 API入门系列之统计学生成绩版本2(十八)
不多说,直接上代码. 统计出每个年龄段的 男.女 学生的最高分 这里,为了空格符的差错,直接,我们有时候,像如下这样的来排数据. 代码 package zhouls.bigdata.myMapRedu ...
- WPF 漏斗控件 等待沙漏效果
由于WPF中不支持gif图片因此要实现一个漏斗沙漏效果有点小麻烦. 网上有一款开源的控件 理论上完全开源 官网 http://wpfspark.codeplex.com/贴一下效果图 大家感觉需要就在 ...
- Nginx介绍及知识点(摘抄)
正向代理是把自己的网络环境切换成代理的网络 反向代理是代理机器返回给我要我的资源 本文借鉴参考于http://tengine.taobao.org/book/chapter_02.html. 属于纯干 ...
- 前端-js进阶和JQ源码思维导图笔记
看不清的朋友右键保存或者新窗口打开哦!喜欢我可以关注我,还有更多前端思维导图笔记
- 利用JavaScript的%做隔行换色
<html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...