如何强制Hibernate将日期返回为java.util.Date而不是Timestamp?

如何强制Hibernate将日期返回为java.util.Date而不是Timestamp?,第1张

如何强制Hibernate将日期返回为java.util.Date而不是Timestamp?

因此,我花了一些时间解决这个问题,并找到了解决方案。它不是一个漂亮的东西,但至少是一个起点-也许有人会用一些有用的注释来补充它。

我在处理中发现的一些有关映射的信息:

  • 包含Hibernate类型到属性类型的基本映射的类是org.hibernate.type.TypeFactory。所有这些映射都存储在不可修改的映射中
        private static final Map BASIC_TYPES;    ...    basics.put( java.util.Date.class.getName(), Hibernate.TIMESTAMP );    ...    BASIC_TYPES = Collections.unmodifiableMap( basics );

如您所见,java.util.Date类型与Hibernate类型org.hibernate.type.TimestampType相关联

  • 下一个有趣的时刻-创建Hibernate org.hibernate.cfg.Configuration-包含有关映射类的所有信息的对象。此类及其属性可以像这样提取:
        Iterator clsMappings = cfg.getClassMappings();    while(clsMappings.hasNext()){        PersistentClass mapping = (PersistentClass) clsMappings.next();        handleProperties(mapping.getPropertyIterator(), map);    }
  • 绝大多数属性是org.hibernate.mapping.Simplevalue类型的对象。我们的兴趣点是方法Simplevalue.getType()-在此方法中定义了在处理DB时将使用哪种类型来回转换属性值
        Type result = TypeFactory.heuristicType(typeName, typeParameters);

至此,我了解到我无法修改BASIC_TYPES(这是唯一的方法),无法将Simplevalue对象替换为java.util.Date类型的属性,更改为我的自定义对象,从而可以知道要转换的确切类型。

解决方案:

  • 通过扩展HibernatePersistence类并覆盖其方法createContainerEntityManagerFactory来创建自定义容器实体管理器工厂:
     public class HibernatePersistenceExtensions extends HibernatePersistence {        @Override        public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) { if ("true".equals(map.get("hibernate.use.custom.entity.manager.factory"))) {     return CustomeEntityManagerFactoryFactory.createCustomEntityManagerFactory(info, map); } else {     return super.createContainerEntityManagerFactory(info, map); }        }    }
  • 创建Hibernate配置对象,修改java.util.Date属性的值对象,然后创建自定义实体管理器工厂。
        public class ReattachingEntityManagerFactoryFactory {        @SuppressWarnings("rawtypes")        public static EntityManagerFactory createContainerEntityManagerFactory(        PersistenceUnitInfo info, Map map) { Ejb3Configuration cfg = new Ejb3Configuration(); Ejb3Configuration configured = cfg.configure( info, map ); handleClassMappings(cfg, map); return configured != null ? configured.buildEntityManagerFactory() : null;        }        @SuppressWarnings("rawtypes")        private static void handleClassMappings(Ejb3Configuration cfg, Map map) { Iterator clsMappings = cfg.getClassMappings(); while(clsMappings.hasNext()){      PersistentClass mapping = (PersistentClass) clsMappings.next();      handleProperties(mapping.getPropertyIterator(), map); }        }         private static void handleProperties(Iterator props, Map map) { while(props.hasNext()){      Property prop = (Property) props.next();      Value value = prop.getValue();      if (value instanceof Component) {          Component c = (Component) value;          handleProperties(c.getPropertyIterator(), map);      } else {          handleReturnUtilDateInsteadOfTimestamp(prop, map);      }  }        private static void handleReturnUtilDateInsteadOfTimestamp(Property prop, Map map) { if ("true".equals(map.get("hibernate.return.date.instead.of.timestamp"))) {     Value value = prop.getValue();     if (value instanceof Simplevalue) {         Simplevalue simplevalue = (Simplevalue) value;         String typeName = simplevalue.getTypeName();         if ("java.util.Date".equals(typeName)) {  UtilDateSimplevalue udsv = new UtilDateSimplevalue(simplevalue);  prop.setValue(udsv);         }     } }        }    }

如您所见,我只是遍历每个属性,并用Simplevalue-object替换UtilDateSimplevalue来替换类型java.util.Date的属性。这是一个非常简单的类-它实现与Simplevalue对象相同的接口,例如org.hibernate.mapping.KeyValue。在构造函数中,将传递原始Simplevalue对象-
因此,每次调用UtilDateSimplevalue都会被重定向到原始对象,但有一个异常-方法getType(…)返回我的自定义类型。

    public class UtilDateSimplevalue implements KeyValue{        private Simplevalue value;        public UtilDateSimplevalue(Simplevalue value) { this.value = value;        }        public Simplevalue getValue() { return value;        }        @Override        public int getColumnSpan() { return value.getColumnSpan();        }        ...        @Override        public Type getType() throws MappingException { final String typeName = value.getTypeName(); if (typeName == null) {         throw new MappingException("No type name"); } Type result = new UtilDateUserType(); return result;        }        ...    }
  • 最后一步是UtilDateUserType的实现。我只是扩展了原始的org.hibernate.type.TimestampType并覆盖了它的方法get(),如下所示:
        public class UtilDateUserType extends TimestampType{        @Override        public Object get(ResultSet rs, String name) throws SQLException { Timestamp ts = rs.getTimestamp(name); Date result = null; if(ts != null){     result = new Date(ts.getTime()); } return result;        }    }

就这些。有点棘手,但是现在每个java.util.Date属性都作为java.util.Date返回,而无需对现有代码进行任何其他修改(注释或修改setter)。



欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5124441.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-17
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存