1. 程式人生 > >hibernate實現資料實體複製儲存

hibernate實現資料實體複製儲存

hibernate實現資料實體複製儲存

2013年12月16日 11:57:22 閱讀數: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.