因此,我花了一些时间解决这个问题,并找到了解决方案。它不是一个漂亮的东西,但至少是一个起点-也许有人会用一些有用的注释来补充它。
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相关联
Iterator clsMappings = cfg.getClassMappings();
while(clsMappings.hasNext()){
PersistentClass mapping = (PersistentClass) clsMappings.next();
handleProperties(mapping.getPropertyIterator(), map);
}
Type result = TypeFactory.heuristicType(typeName, typeParameters);
至此,我了解到我无法修改BASIC_TYPES(这是唯一的方法),无法将SimpleValue对象替换为java.util.Date类型的属性,更改为我的自定义对象,从而可以知道要转换的确切类型。
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);
}
}
}
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;
}
...
}
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)。