因此,我花了一些时间解决这个问题,并找到了解决方案。它不是一个漂亮的东西,但至少是一个起点-也许有人会用一些有用的注释来补充它。
我在处理中发现的一些有关映射的信息:
- 包含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)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)