Java框架之Hibernate(四)
本文主要介绍:
1 悲观锁和乐观锁
2 使用版本号控制并发访问
3 flush方法和批量更新的问题
4 DetachedCriteria
5 N + 1 次查询
6 使用sql进行查询
7 注解方式
一、悲观锁和乐观锁
问题:有两个人,同时打开了一个贴子,进行编辑,结果会怎么样? 后提交的,有可能会把先提交的冲掉。
比如一个贴子,发表者是张三
第一个人,改成李四,第二个改成王五,后提交,结果最后是王五,李四没了
==悲观锁: 操作员得到数据以后,别人就不能修改,直到他修改完成,事务提交后才能进行
==乐观锁: 加标志位,以标位(版本号)的形式进行控制
假如说读过来的时候它的版本号是0,然后它就会去提交,提交会更新这个版本号,比如给它加一,如果同时有另一个人也读了这个版本是0的数据,他后提交,提交的时候,发现版本号不是0了,证明这东西被别人动过了,要么重新读入,要么放弃修改。
Hibernate支持乐观锁。当多个事务同时对数据库表中的同一条数据操作时,如果没有加锁机制的话,就会产生脏数据(duty data)。Hibernate有2种机制可以解决这个问题:
乐观锁和悲观锁。这里我们只讨论乐观锁。
Hibernate乐观锁,能自动检测多个事务对同一条数据进行的操作,并根据先胜原则,提交第一个事务,其他的事务提交时则抛出org.hibernate.StaleObjectStateException异常。
二、使用版本号控制并发访问
1) 在数据库中增加一个字段, versionNo (叫什么名都可以),整型 (或timestamp 型)
2) 对应的实体类中,也加一个相同的字段
3) 在配置文件 Userinfo.xml 中增加一个配置 <version name="versionNo" /> //放在id之后,所有的其他属性之前
- //例子
- Userinfo user1=(Userinfo) HibUtil.get(Userinfo.class,505 );
- Userinfo user2=(Userinfo) HibUtil.get(Userinfo.class,505 );
- //user1 和 user2 对应着数据库中的同一条数据
- try{
- user1.setUserName("这是张三给起的名");
- HibUtil.update(user1);
- user2.setUserName("这是赵明明给启的名");
- HibUtil.update(user2);
- }
- catch(StaleObjectStateException ex ){
- System.out.println("数据已被别人修改!保存失败");
- }
- /*org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction */
三、flush方法和批量更新的问题
- //例一
- public static void main(String[] args) {
- Session s=HibUtil.getSession();
- Userinfo user=new Userinfo();
- user.setUserName("aaa");
- Userinfo user2=new Userinfo();
- user2.setUserName("aaa");
- Transaction tx=s.beginTransaction();
- s.save(user); //key
- s.save(user2); //
- //s.flush(); //强制进行缓存的同步
- System.out.println("--------我是不是先打印???----------"); //横线出现在save之前
- tx.commit();
- HibUtil.closeSession();
- }
说明:
1)如果主键生成器是hilo
在不写 flush的情况下,可以发现横线是先输出,再执行save,因为hibernate总是试图把进行数据库访问的操作往后拖。上面的两条save语句,实际上是先把数据添到一级缓存中了,在最后commit 的时候,再进行数据库访问
2)如果加上 s.flush(); 表示强制要求hibernate刷新一级缓存中的数据,这时hibernate被迫,要将缓存中的数据存到数据库中,所以必须执行sql语句, 横线就会出现在save 之后了。
3)如果 主键生成器改成 native , 由于hibernate只有在知道主键的情况下才能进行一级缓存的填充,而native主键生成器是必须把数据保存到数据库以后才能得到生成的主键的,所以save方法会先执行。
用StatelessSession接口:它不和一级缓存、二级缓存交互,也不触发任何事件、监听器、拦截器,通过该接口的操作会立刻发送给数据库,与JDBC的功能一样。
StatelessSession s = sessionFactory.openStatelessSession(); 该接口的方法与Session类似
StatelessSession 没有 save 但有 insert
四、DetachedCriteria
最大的好处,是可以在Session外进行创建
- //例子
- public class UserAction {
- public static void main(String[] args) {
- Scanner scan=new Scanner(System.in);
- System.out.println("请输入用户名");
- String userName=scan.nextLine();
- System.out.println("请输备注");
- String note=scan.nextLine();
- DetachedCriteria dc= DetachedCriteria.forClass(Userinfo.class);
- if(userName!=null && (!"".equals(userName))){
- dc.add(Restrictions.eq("userName", userName));
- }
- if(note!=null && (!"".equals(note))){
- dc.add(Restrictions.eq("note", note));
- }
- UserDao dao=new UserDao();
- List<Userinfo> userList=dao.search(dc);
- System.out.println("================结果================");
- for (Userinfo u : userList) {
- System.out.println(u);
- }
- }
- }
- public class UserDao {
- // 多条件查询
- public List<Userinfo> search(DetachedCriteria dc) {
- try {
- Session s = HibUtil.getSession();
- Criteria c = dc.getExecutableCriteria(s);
- return c.list();
- }
- finally {
- HibUtil.closeSession();
- }
- }
- }
五、N + 1 次查询
用Query.iterator可能会有 N+1次查询。n+1次查询,是指第一次,只查出来id, 然后才查它的内容,而且多数是从缓存里拿的。
- // 注意,这里在使用 q.iterate() 这种迭代的时候才会出现 N+1 次查询
- public static void queryUser(){
- Session s=HibUtil.getSession();
- Query q=s.createQuery("from UserInfo");
- Iterator<UserInfo> it=q.iterate();
- while(it.hasNext()){
- UserInfo u=it.next();
- System.out.println(u.getUserName());
- }
- s.close();
- }
六、使用sql进行查询
例一:
- public static void main(String[] args) {
- List<Userinfo > userList=getUserList();
- for (Userinfo u : userList) {
- System.out.println(u);
- }
- }
- public static List<Userinfo> getUserList() {
- try {
- Session s = HibUtil.getSession();
- // s.createQuery(queryString);
- String sql = "select * from userinfo"; //用的sql语句,后面是表名
- SQLQuery q = s.createSQLQuery(sql).addEntity(Userinfo.class); //不要忘了指定类型
- return q.list();
- } finally {
- HibUtil.closeSession();
- }
- }
例二 :
使用sql进行关联查询,返回的结果 List<Object[]>
- //main 方法 :
- List<Object[]> listObj=getUserList2();
- for (Object[] fields : listObj) {
- for (Object field : fields) {
- System.out.print(field +"\t");
- }
- System.out.println();
- }
- public static List<Object[]> getUserList2(){
- try {
- Session s = HibUtil.getSession();
- String sql="select a.id,a.fahao,b.name from nigu a left join niguan b on a.niguan_id=b.id";
- SQLQuery q = s.createSQLQuery(sql);
- return q.list();
- } finally {
- HibUtil.closeSession();
- }
- }
例三:
使用Dto进行数据传输 (Dto 是数据传输对象)
- //main 方法:
- List<NiGuDto> niguList=getUserList3();
- for (NiGuDto n : niguList) {
- System.out.println(n);
- }
- public static List<NiGuDto> getUserList3(){
- try {
- Session s = HibUtil.getSession();
- String sql="select a.id,a.fahao,b.name from nigu a left join niguan b on a.niguan_id=b.id";
- Query q=s.createSQLQuery(sql);
- q.setResultTransformer(Transformers.aliasToBean(NiGuDto.class)); //进行数据传输对象的处理
- return q.list();
- } finally {
- HibUtil.closeSession();
- }
- }
七、注解方式
1) 导包
2) 配置
- @Entity
- @Table(name="User_info")
- public class Userinfo implements java.io.Serializable {
- private String note;
- private Integer versionNo;
- private Integer id; //主键相关的注解一般都放在get方法
- private String userName;
- @Id
- @GeneratedValue
- public Integer getId() {
- return this.id;
- }
- ....
- }
注意:
- //1.在主配置文件中要加入
- <mapping class="cat.beans.Userinfo" />
- //2.在工具类中的
- //Configuration cxf=new Configuration(); 要换成下面的写法
- Configuration cxf=new AnnotationConfiguration(); //3.3 要这样做
Java框架之Hibernate(四)的更多相关文章
- java框架篇---hibernate入门
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任何使用JDB ...
- JAVA框架:hibernate(四)
一.绑定本地session 原理:之前connection实现事务一个道理,2种方法:1.变量下传.2.因为servlet是单线程,和本地当前线程绑定. 配置: 1)配置核心配置文件hibernate ...
- Java框架之Hibernate(三)
本文主要讲解: 1 级联 cascade 关键字 2 级联删除 3 inverse 关键字 4 懒加载 5 缓存的模拟 6 Hibernate 的一级缓存 7 Hibernate 的二级缓存 一.级联 ...
- Java框架之Hibernate(一)
一.Hibernate - 核心接口 它是 JBoss Community team (社区团队) 开发的.Hibernate 是一个开源的,对象关系模型框架 (ORM),它对JDBC进行了轻量的封 ...
- java框架之Hibernate(2)-持久化类&主键生成策略&缓存&事务&查询
持久化类 概述 持久化:将内存中的对象持久化到数据库中的过程就是持久化.Hibernate 就是用来进行持久化的框架. 持久化类:一个 Java 对象与数据库的表建立了映射关系,那么这个类在 Hibe ...
- Java框架之Hibernate(二)
本文主要介绍: 1 Criteria 接口 2 用 myeclipse 反向生成 3 hibernate 主键生成策略 4 多对一 5 一对多 6 使用List 集合的一对多 7 多对多 一.Cri ...
- JAVA框架之Hibernate框架的学习步骤
首先介绍一下Java三大框架的关系 以CRM项目即客户关系管理项目示例 hibernate框架的学习路线: 1.学习框架入门,自己搭建框架,完成增删改查的操作 2.学习一级缓存,事物管理和基本查询 3 ...
- java框架之Hibernate(1)-简介及初使用
简介 hibernate 是一个开源 ORM ( Object / Relationship Mipping ) 框架,它是对象关联关系映射的持久层框架,它对 JDBC 做了轻量级的封装,而我们 ja ...
- java框架篇---hibernate之缓存机制
一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...
随机推荐
- 機器學習基石 (Machine Learning Foundations) 作业1 Q15-17的C++实现
大家好,我是Mac Jiang.今天和大家分享Coursera-台湾大学-機器學習基石 (Machine Learning Foundations) -作业1的Q15-17题的C++实现. 这部分作业 ...
- HBase源代码分析之HRegion上MemStore的flsuh流程(一)
了解HBase架构的用户应该知道,HBase是一种基于LSM模型的分布式数据库.LSM的全称是Log-Structured Merge-Trees.即日志-结构化合并-树. 相比于Oracle普通索引 ...
- 基于.NET的弹性及瞬间错误处理库Polly
本文基本是官方说明的翻译和总结(https://github.com/App-vNext/Polly) 什么是Polly? Polly是一款基于.NET的弹性及瞬间错误处理库, 它允许开发人员以顺畅及 ...
- mysql新建数据库,并设置charset为utf8,使用utf8_general_ci字符集校验结果
一. 实现功能 有时候在linux服务器端, 会在mysql命令行中, 创建数据库, 今天讲一下怎么在创建数据库时, 把charset设置为utf8,collate设置为utf8_general_ci ...
- MVC+EF 入门教程(四)
一.前言 写了那么久,那么现在给大家看效果了 二.效果展示 点击创建Blog 显示 编辑 编辑成功,是不是很酷. 删除 终于完成了,准备睡觉!虽然有很多不足的地方,我会慢慢的去改的.感谢累了一天的自己 ...
- MVC系列——一个异常消息传递引发的思考
前言:最近在某个项目里面遇到一个有点纠结的小问题,经过半天时间的思索和尝试,问题得到解决.在此记录一下解决的过程,以及解决问题的过程中对.net里面MVC异常处理的思考.都是些老生常谈的问题,不多说, ...
- iOS UIAlertController中加入倒计时,输入框,Swift讲解
一.倒计时 @interface ViewController () { UIAlertController *alertview; NSString * message; NSTimer * wai ...
- iOS 通知的变化ios9-10,新功能展示
二.新功能展示 1 使用 /iOS通知新功能玩法 2. 全面 iOS10里的通知与推送详情 一.变化 四.Notification(通知) 自从Notification被引入之后,苹果就不断的 ...
- .net 委托的使用方法以及使用委托的好处
使用方法: //无返回值无参数委托的定义方法 public delegate void NoReturnPara(); 给委托赋值的几种方式 //实例化委托,并传入方法 NoReturbNoPara ...
- python 中一些关键字的区别
一.raw_input 和input input和raw_input都可以读取控制台的输入,但是input和raw_input在处理数字时是有区别的 1.当输入为纯数字时 input返回的是数值类型, ...