hibernate实现数据实体复制保存

2013年12月16日 11:57:22 Hardy008 阅读数:3474
 

描述:需要将数据的一条记录进行复制保存为一条新记录。

思路:从数据库中取得一条记录封装到对象中,然后改变此对象的主键,保存此对象即可。

分析:看起来很简单快捷吧,但事实并非如此,执行出错“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一个对象一样,但是简单了很多,代码如下:

  1. public class CopyHandle extends LoggerBase {
  2. private static CopyHandle instance = null;
  3.  
  4. private CopyHandle(){}
  5. public static CopyHandle getInstance(){
  6. if(null == instance){
  7. instance = new CopyHandle();
  8. }
  9. return instance;
  10. }
  11.  
  12. public Object copy(Object object) {
  13. Object objectCopy = null;
  14. try {
  15. if(null == object) return null;
  16.  
  17. Class<?> classType = object.getClass();
  18. Field fields[] = classType.getDeclaredFields();
  19.  
  20. objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {});
  21.  
  22. Field field = null;
  23. String suffixMethodName;
  24. Method getMethod, setMethod;
  25. Object value = null;
  26. for (int i = 0; i < fields.length; i++) {
  27. field = fields[i];
  28. suffixMethodName = field.getName().substring(0, 1).toUpperCase() + (field.getName().length()>1?field.getName().substring(1):"");
  29.  
  30. getMethod = classType.getMethod("get" + suffixMethodName, new Class[] {});
  31. setMethod = classType.getMethod("set" + suffixMethodName, new Class[] { field.getType() });
  32.  
  33. value = getMethod.invoke(object, new Object[] {});
  34. if(null == value){
  35. if(field.getType().getName().equalsIgnoreCase("java.lang.String")){
  36. setMethod.invoke(objectCopy, new Object[] { "" });
  37. }
  38. } else {
  39. setMethod.invoke(objectCopy, new Object[] { value });
  40. }
  41. }
  42. } catch (NoSuchMethodException e) {
  43. // TODO: handle exception
  44. this.logger.error("CopyHandle.copy(): NoSuchMethodException: "+ e);
  45. } catch (Exception e) {
  46. // TODO: handle exception
  47. this.logger.error("CopyHandle.copy(): Exception: "+ e);
  48. }finally{
  49. return objectCopy;
  50. }
  51. }
  52.  

最新文章

  1. Python 学习之路 (前言)
  2. WPF VlC 实现视频的播放(1)
  3. SPRING IN ACTION 第4版笔记-第十章Hitting the database with spring and jdbc-002-本章的源代码
  4. JavaScript 应用开发 #4:切换任务的完成状态
  5. hdoj 2094 产生冠军
  6. 超炫的时间轴jquery插件Timeline Portfolio
  7. 控制语句 for while if switch
  8. css样式清零及常用类
  9. Linux显示指定区块大小为1048576字节
  10. Redis之Set
  11. localstorage 更新监测 storage事件
  12. 【Zookeeper系列】ZooKeeper伸缩性(转)
  13. VS2008中开发智能设备程序的一些总结收藏
  14. Let&#39;s Encrypt申请免费SSL证书
  15. CentOS6安装各种大数据软件 第八章:Hive安装和配置
  16. DP_括号匹配序列问题
  17. 关于oracle的sequence和trigger。
  18. CAS单点登录------302个没完没了
  19. PAT 天梯赛 L1-043 阅览室
  20. shutil——高级的 文件、文件夹、压缩包 处理模块

热门文章

  1. Vue学习计划基础笔记(二) - 模板语法,计算属性,侦听器
  2. 【TCP_协议_socket接口】-jmeter
  3. Java Basic&amp;Security Tools
  4. Farm Irrigation ZOJ 2412(DFS连通图)
  5. Unicode 和 UTF-8 有何区别
  6. ipv6问题
  7. virtual judge 本地部署方案
  8. Spring学习(四)—— java动态代理(JDK和cglib)
  9. DNS测试工具的使用(了解)
  10. zabbix简介