-
java hibernate 持久化对象 深复制
2014-07-24 17:02:57现在有一个从数据库取出来的持久化对象,对象内包含了好多其他持久化对象的集合 我想把这个持久化对象及里面其他的对象全部深复制,然后再插入到数据库中,怎样实现好。。。 -
Hibernate持久化对象修改id重新保存的办法——Hibernate学习记录二
2017-11-10 20:16:48点击修改,对一条发布状态的记录进行复制,并生成一个草稿版本,也就是同一条记录的不同状态,也就出现需要从数据库get之后把id置空重新保存,这里出现一个问题,但Hibernate的持久化对象是无法对id进行修改操作的,...昨天在工作中遇到一个特殊的场景,点击修改,对一条发布状态的记录进行复制,并生成一个草稿版本,也就是同一条记录的不同状态,也就出现需要从数据库get之后把id置空重新保存,这里出现一个问题,但Hibernate的持久化对象是无法对id进行修改操作的,需要重新new一个全新的对象存储才可以,但Java中的机制,如果采用new Object()并赋值的的方式并不是真的产生一个新的对象,而是引用赋值,即传递内存地址,学过C语言的很容易理解。
要实现这种需求,就要复制出一个全新的对象,Java提供了一种解决办法——对象克隆。
对象克隆的方法:
实体类实现Cloneable接口,然后在实体类中重写clone()方法,以User类为例,如下所示:
这样使用的时候,User user1 = new User(); User user2 = user1.clone();即可将user1的所有属性值复制给user2,但他们是两个对象,而不是同一个对象的引用。之后可以进行id的修改,然后用Hibernate进行保存,生成一条新的记录。package com.domain; /** * Created by Jiro.Chen on 2017/11/6. */ public class User implements Cloneable { private String id; private String name; private Integer age; private String address; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (id != null ? !id.equals(user.id) : user.id != null) return false; if (name != null ? !name.equals(user.name) : user.name != null) return false; if (age != null ? !age.equals(user.age) : user.age != null) return false; if (address != null ? !address.equals(user.address) : user.address != null) return false; return true; } public int hashCode() { int result = id != null ? id.hashCode() : 0; result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (age != null ? age.hashCode() : 0); result = 31 * result + (address != null ? address.hashCode() : 0); return result; } @Override public Object clone(){ User user = null; try { user = (User)super.clone(); }catch (CloneNotSupportedException e){ e.printStackTrace(); } return user; } }
-
hibernate如何操作持久化对象,以及其生命周期和作用
2020-03-13 11:42:38hibernate操作持久化对象是通过session缓存来实现的。 什么是缓存? 缓存介于应用程序和永久性存储源之间,他的作用是降低应用程序直接读写永久性存储源的频率,从而提高应用的运行效率; 缓存内的数据是永久性存储...hibernate操作持久化对象是通过session缓存来实现的。在下面的会一步一步进行解析其工作原理。
什么是缓存?
缓存介于应用程序和永久性存储源之间,他的作用是降低应用程序直接读写永久性存储源的频率,从而提高应用的运行效率; 缓存内的数据是永久性存储源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件同步缓存和永久性存储源的数据。
什么是session缓存?
session接口的实现类sessionImpl中定义了一系列的Java集合,这些集合构成了session的缓存。
Session session = sessionFactory.openSession(); ...... session.close();
session缓存是如何工作的?
当session执行查询方法时,先从session缓存中读取数据,如果缓存中有则直接读取,如果缓存中没有,从数据库中查询并加载到session缓存中,再从缓存中读取;
当session执行save()、update()方法时,将对象持久化到数据库中并将对象加载到session缓存中;session清理缓存?
session在某一时间点按照缓存中对象的属性变化来同步更新数据库的这一过程被称为“session清理缓存”
清理缓存的时间点:
当调用`transaction.commit() `方法时,会先清理缓存,在向数据库提交事务; 当显式调用`Session.flush() `时,会清理缓存; 当调用session的查询(不包括load()和get()方法)时,如果缓存中对象的属性有变化则清理缓存;
session缓存的三个作用:
减少数据库的访问次数,提高数据访问的效率 保证缓存中的对象与数据库中相关的记录同步 避免死循环以及死循环引起的堆栈溢出异常;【OID机制】
hibernate对象的生命周期:
实体对象的四种状态:
transient(临时状态):刚刚被new创建,还没有被持久化,不在session缓存中 persistent(持久化状态):已经被持久化,并加入到session缓存中 detached(游离状态):已经被持久化,但不再处于session缓存中 removed(删除状态):session已经计划将其从数据库中删除,并且不在处于session缓存中;
hibernate操作持久化对象:
session的save方法
把对象加入缓存中,使其变成持久化对象 根据映射文件配置的标识符生成器为对象分配一个OID; 计划执行一个insert,把对象当前属性值组装到insert语句中 事务提交后(transaction.commit())永久的将数据保存在数据库中
session的update方法
把游离对象重新加入session缓存中,使其变为持久化对象 计划执行一个update,将对象当前属性组装到update语句,执行update语句; 事务提交后(transaction.commit())永久的将数据保存到数据库中; 不管对象属性有没有改变都会执行update(通过设置<class>的select-before-update=true改变)
session的savaOrupdate()方法
session的delete()方法
检查传入的参数是否是持久化对象,如果是将其移出session缓存 计划执行一个delete,但是并不执行 当session清理缓存时才执行delete,比如执行`session.flush()`
hibernate区分临时对象
对象的OID为null 映射文件中设置了<id>的unsaved-value属性,并且对象的id值与unsaved-value设置的值相等;
session的load()和get()方法
相同点:
load和get方法都是根据OID加载持久化对象
不同点:
如果数据库中不存在与OID对应的记录: load会抛出ObjectNotFoundException异常 get会返回null; 默认加载策略 load使用类的延迟加载策略 get使用类的立即加载策略
-
hibernate实现数据实体复制保存
2013-12-23 09:01:44分析:看起来很简单快捷吧,但事实并非如此,执行出错“identifier of the object was alter from 1 to 10”,因为从数据库中取得的对象是持久化对象。在hibernate的缓存中有一个备份。当你修改了持久化对描述:需要将数据的一条记录进行复制保存为一条新记录。
思路:从数据库中取得一条记录封装到对象中,然后改变此对象的主键,保存此对象即可。
分析:看起来很简单快捷吧,但事实并非如此,执行出错“identifier of the object was alter from 1 to 10”,因为从数据库中取得的对象是持久化对象。在hibernate的缓存中有一个备份。当你修改了持久化对象,提交事务时,hibernate就会比较当前对象和在缓存中备份的对象,如果不一样则更新数据库。这里需要注意:更新是根据主键更新的:也就是 update tablename set ... where 主键=‘?’。 但是如果你把主键的值改了,hibernate在更新的时候就无法更新数据库了,所以就产生了上面的错误。
解决的办法有三种:
解决办法一:evict(object) :在改变对象主键之前。利用evict方法清理hibernate缓存,此对象将不再是持久化对象,所以不会去更新数据库。成功。但是hibernate不提倡用此方法
解决办法二:重新new一个对象,把原来的对象的属性值一一set进来,然后保存。重新new的对象是瞬时对象,保存成功。但如果存在大量的属性,或者此表存在子表数量多,那么必须为每个表的对象都new一次,然后赋值。这将很耗时,非常讨厌。
解决办法三:利用java反射机制复制一个对象出来,效果的new一个对象一样,但是简单了很多(ps:java反射机制复制对象,到底能提高多少效率,值得商榷),代码如下:
-
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class CopyObject {
public static Object copy(Object object) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Object objectCopy = null;
if(null == object) return null;
Class<?> classType = object.getClass();
//取原对象的属性
Field fields[] = classType.getDeclaredFields();
//创建赋值对象
objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});
Field field = null;
String suffixMethodName;
Method getMethod, setMethod;
Object value = null;
for(int i = 0; i < fields.length; i++) {
field = fields[i];
suffixMethodName = field.getName().substring(0, 1).toUpperCase() + (field.getName().length()>1?field.getName().substring(1):"");
getMethod = classType.getMethod("get" + suffixMethodName, new Class[] {});
setMethod = classType.getMethod("set" + suffixMethodName, new Class[] { field.getType() });
value = getMethod.invoke(object, new Object[] {});
if(null == value){
if(field.getType().getName().equalsIgnoreCase("java.lang.String")){
setMethod.invoke(objectCopy, new Object[] { "" });
}
}else{
setMethod.invoke(objectCopy, new Object[] { value });
}
}
return objectCopy;
}
}
-
import java.lang.reflect.Field;
-
hibernate复制数据库中一条记录
2012-02-15 15:50:59最近在用hibernate的时候产生一个问题。我的目的是复制一条记录。思路:从数据库中取得一条记录封装到对象中...开始从网上搜索,最终找到了原因:从数据库中取得的对象是持久化对象。在hibernate的缓存中有一个备份。当最近在用hibernate的时候产生一个问题。我的目的是复制一条记录。思路:从数据库中取得一条记录封装到对象中,然后改变此对象的主键,最后保存此对象。看似很正确的思路却产生了错误:identifier of the object was alter from 1 to 10。 这是为什么呢?开始从网上搜索,最终找到了原因:从数据库中取得的对象是持久化对象。在hibernate的缓存中有一个备份。当你修改了持久化对象,提交事务时,hibernate就会比较当前对象和在缓存中备份的对象,如果不一样则更新数据库。这里需要注意:更新是根据主键更新的:也就是 update tablename set ... where 主键=‘?’。 但是如果你把主键的值改了,hibernate在更新的时候就无法更新数据库了,所以就产生了上面的错误。 所以为了达到我的目的,持久化对象是不能修改的。怎么解决的,哭死冥想,终于解决了..而解决的办法有三种:解决办法一:evict(object) :在改变对象主键之前。利用evict方法清理hibernate缓存,此对象将不再是持久化对象,所以不会去更新数据库。成功。但是hibernate不提倡用此方法解决办法二:重新new一个对象,把原来的对象的属性值一一set进来,然后保存。重新new的对象是瞬时对象,保存成功。但如果存在大量的属性,或者此表存在子表数量多,那么必须为每个表的对象都new一次,然后赋值。这将很耗时,非常讨厌。解决办法三:利用java反射机制复制一个对象出来,效果的new一个对象一样,但是简单了很多,代码如下:public static Object copy(Object object) throws Exception {Class<?> classType = object.getClass();Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});Field fields[] = classType.getDeclaredFields();for (int i = 0; i < fields.length; i++) {Field field = fields[i];String fieldName = field.getName();String firstLetter = fieldName.substring(0, 1).toUpperCase();String getMethodName = "get" + firstLetter + fieldName.substring(1);String setMethodName = "set" + firstLetter + fieldName.substring(1);Method getMethod = classType.getMethod(getMethodName,new Class[] {});Method setMethod = classType.getMethod(setMethodName,new Class[] { field.getType() });Object value = getMethod.invoke(object, new Object[] {});setMethod.invoke(objectCopy, new Object[] { value });}return objectCopy;} 到此为止,问题解决....
-
Hibernate 笔记
2009-12-25 20:31:00merge: 将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象 。如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回,传入对象依然保持... -
hibernate中merge/attachDirty/attachClean
2009-05-12 15:46:27merge:将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象 。如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回,传入对象依然保持... -
Hibernate生成的DAO类中的方法说明
2007-09-27 14:22:00Hibernate生成的DAO类中的方法说明/** * 将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象。 * 如果该session中没有关联的持久化对象,加载一个。 * 如果传入对象未保存,保存一个副本并... -
关于hibernate的merge、attachDirty、attachClean方法的应用
2015-09-24 10:08:33*将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象。 *如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回,传入对象依然保持detached... -
hibernate中merge()、attachDirty()、attachClean()
2012-05-22 23:10:13* 将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象 * 如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回,传入对象依然保持... -
Hibernate逍遥游记.pdf
2012-12-02 19:54:29《Hibernate逍遥游记》由浅入深地介绍运用目前最成熟的Hibernate3.3 版本进行Java对象持久化的核心技术。《Hibernate逍遥游记》主要介绍通过Hibernate API来访问数据库的方法,还介绍把Java对象模型映射到关系数据... -
hibernate自动生成的DAO类中的merge() attachDirty() attachClean()方法简单介绍
2014-11-29 11:22:09* 将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象。 * 如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回,传入对象依然保持... -
关于Hibernate的merge() attachDirty() attachClean()三种方法比较使用
2009-09-16 20:22:00*将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象。 *如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回,传入对象依然保持... -
hibernate中merge()、attachDirty()、attachClean()这三个方法是做什么的?怎么用?
2011-12-08 13:46:20* 将传入的detached状态的对象的属性复制到持久化对象中,并返回该持久化对象 * 如果该session中没有关联的持久化对象,加载一个,如果传入对象未保存,保存一个副本并作为持久对象返回,传入对象依然保持detached... -
Hibernate缓存机制-总结
2010-11-04 10:01:26缓存: 是临时存放复制数据的内存区域(Hibernate 分持久化对象和ID列表) 缓存作用:查询数据时,首先到缓存中去查找,减少数据库的SQL访问 >一级缓存,二级缓存和查询缓存都打开的情况下作查询操作时这样的:... -
hibernate3.2中文文档(chm格式)
2014-08-16 08:01:39HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate... -
J2EE系列之Hibernate4学习笔记(七)--Session常用方法
2017-05-12 13:49:52一、save()方法,这个方法应该已经非常熟悉了,它能把对象又临时状态转变成持久化状态。 1.复制工程Hibernate04-02为Hibernate05-02,去掉用不到的Node类相关的代码。 2.修改StudentTest.java文件为: package ... -
hibernate 第二次深入接触
2016-08-29 15:14:001.session 到底如何进行脏处理? 当一个Dept对象加入到session缓存时,Session会为... 用来持久化数据的唯一标示,在小配置里面的id标签中存在 3.主键生成策略 Uuid:32位的16进制数 4.PO VO DTO PO=javabean ... -
Hibernate:merge(),attachDirty(),attachClean()
2010-01-22 16:05:58学java和asp.net的朋友-免费的浪曦java视频和asp.net视频下载... // 关于merge() attachDirty() attachClean()三种方法下面做一个简单的介绍 /** * 将传入的detached状态的对象的属性复制到持久化对象中,并返回该持... -
Hibernate方法save、update、merge、saveOrUpdate及get和load的区别
2018-05-12 18:27:57一、update 和 merge的区别首先在执行更新操作的时候,两者都必须要有idupdate是直接执行update 语句,执行后状态为持久化状态而merge则不一样:1. 如果session中有与之对应的对象,也就是主键相同,则会把要保存的... -
Hibernate save()、saveOrUpdate()、merge()的区别
2016-09-24 14:53:00update是直接执行update 语句,执行后状态为持久化状态 而merge则不一样: 1. 如果session中有与之对应的对象,也就是主键相同,则会把要保存的obj的值copy给session中的对象,然后update被复制后的session中的... -
EntityManager的merge()方法
2019-03-17 22:54:00EntityManager的merge()方法相当于hibernate中session的saveOrUpdate()方法; 用于实体的插入和更新操作;...持久化新对象; 执行insert插入到数据库; 代码: //merge的第一种情况:临时对象 @Test pu... -
EJB之JPA模块(一)
2013-04-29 15:44:00EJB中的JPA是对对象持久化操作的,jboss中默认的实现是通过hibernate实现。一下是关于jpa的一个小例子。 1. 将%JBOSS_HOME%\docs\examples\jca\mysql-ds.xml复制到%JBOSS_HOME%\server\default\deploy目录下,修改... -
java面试题
2018-01-01 15:35:15持久化状态(persisted) 58 71.5.3. 游离状态(detached) 58 71.5.4. hibernate的三种状态之间如何转换 59 71.6. Hibernate并发机制,并发问题的处理。 59 71.6.1. Hibernate并发机制 59 71.6.2. 并发问题解决方案 59... -
Java Web开发实战1200例(第2卷)(完整版).(清华出版.卢瀚.王春斌).part1
2016-06-13 20:03:04实例083 实现跨数据库的表内容复制 实例084 使用UNION ALL语句批量插入数据 实例085 更新指定记录 实例086 将数据表清空 第4章 SQL语句应用技术 4.1 聚集函数与日期查询 实例087 利用SUM函数实现数据汇总 实例088 ... -
java源码包---java 源码 大量 实例
2013-04-18 23:15:26关于数字签名:产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥... -
Java开发实战1200例.第2卷.part3
2013-05-08 22:46:34实例083 实现跨数据库的表内容复制 156 实例084 使用UNION ALL语句批量插入数据 156 实例085 更新指定记录 157 实例086 将数据表清空 159 第4章 SQL语句应用技术 160 4.1 聚集函数与日期查询 161 实例087 利用SUM... -
Java开发实战1200例.第2卷.part2
2013-05-08 22:45:35实例083 实现跨数据库的表内容复制 156 实例084 使用UNION ALL语句批量插入数据 156 实例085 更新指定记录 157 实例086 将数据表清空 159 第4章 SQL语句应用技术 160 4.1 聚集函数与日期查询 161 实例087 利用SUM... -
Java开发实战1200例.第2卷.part1
2013-05-08 22:44:13实例083 实现跨数据库的表内容复制 156 实例084 使用UNION ALL语句批量插入数据 156 实例085 更新指定记录 157 实例086 将数据表清空 159 第4章 SQL语句应用技术 160 4.1 聚集函数与日期查询 161 实例087 利用SUM...
-
access应用的3个开发实例
-
微信小程序-swiper-item下的列表高度问题解决
-
CentOS7使用NTP服务器
-
关于comsol技术剖析的超强干货
-
项目管理工具与方法
-
samplejavaapp-源码
-
基于Qt的LibVLC开发教程
-
CSS学习(四)——字体样式,文本样式
-
字符串处理
-
数据结构与算法(15):和为s的连续正数序列
-
MongoDB 聚合 -- 连表查询
-
Recipe_Project:在此项目中,我们可以搜索配方中的给定成分-源码
-
DataCleaner---19.2 Building DataCleaner
-
selenium用户验证的两种方式
-
marathon-bigip-ctlr:用于Marathon的F5 BIG-IP控制器的存储库-源码
-
Ajax不能下载文件的问题
-
MySQL 备份与恢复详解(高低版本 迁移;不同字符集 相互转换;表
-
oracle数据库巡检sql
-
clean_nexus.zip
-
NET通用权限框架3.0.rar