kuc*_*ram 2 grails hibernate jpa grails-3.0 hibernate-5.x
有什么方法可以支持在Hibernate 5.1.1中将java.time.ZoneId持久映射到字符串。现在,它以二进制形式保存ZoneId。
我刚刚升级到具有Hibernate 5.1.1的Grails 3.2.1。例如,保存java.time.Instant效果很好,但是java.time.ZoneId仅以二进制形式存储。
我认为没有Hibernate的支持。那么我该如何编码自己的映射。我尝试使用Jadira Framework,但由于启动grails应用程序时存在一些冲突(例外),因此无法使用。
您可以使用JPA 2.1定义的自定义属性转换器。像这样声明转换器类:
@Converter
public static class ZoneIdConverter implements AttributeConverter<ZoneId, String> {
@Override
public String convertToDatabaseColumn(ZoneId attribute) {
return attribute.getId();
}
@Override
public ZoneId convertToEntityAttribute(String dbData) {
return ZoneId.of( dbData );
}
}
Run Code Online (Sandbox Code Playgroud)
然后从类型的实体属性引用它ZoneId:
@Convert(converter = ZoneIdConverter.class)
private ZoneId zoneId;
Run Code Online (Sandbox Code Playgroud)
持久/加载zoneId属性时,将自动调用该转换器。
所以我终于找到了一种实现自定义休眠用户类型的好方法。要将 java.time.ZoneId 持久保存为 varchar,请实现以下用户类型类:
import org.hibernate.HibernateException
import org.hibernate.engine.spi.SessionImplementor
import org.hibernate.type.StandardBasicTypes
import org.hibernate.usertype.EnhancedUserType
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.Types
import java.time.ZoneId
/**
* A type that maps between {@link java.sql.Types#VARCHAR} and {@link ZoneId}.
*/
class ZoneIdUserType implements EnhancedUserType, Serializable {
private static final int[] SQL_TYPES = [Types.VARCHAR]
@Override
public int[] sqlTypes() {
return SQL_TYPES
}
@Override
public Class returnedClass() {
return ZoneId.class
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y) {
return true
}
if (x == null || y == null) {
return false
}
ZoneId zx = (ZoneId) x
ZoneId zy = (ZoneId) y
return zx.equals(zy)
}
@Override
public int hashCode(Object object) throws HibernateException {
return object.hashCode()
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
Object zoneId = StandardBasicTypes.STRING.nullSafeGet(resultSet, names, session, owner)
if (zoneId == null) {
return null
}
return ZoneId.of(zoneId)
}
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
if (value == null) {
StandardBasicTypes.STRING.nullSafeSet(preparedStatement, null, index, session)
} else {
def zoneId = (ZoneId) value
StandardBasicTypes.STRING.nullSafeSet(preparedStatement, zoneId.getId(), index, session)
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value
}
@Override
public boolean isMutable() {
return false
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value
}
@Override
public Object assemble(Serializable cached, Object value) throws HibernateException {
return cached
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original
}
@Override
public String objectToSQLString(Object object) {
throw new UnsupportedOperationException()
}
@Override
public String toXMLString(Object object) {
return object.toString()
}
@Override
public Object fromXMLString(String string) {
return ZoneId.of(string)
}
}
Run Code Online (Sandbox Code Playgroud)
然后您需要在conf/application.groovyGrails 应用程序中注册自定义用户类型:
grails.gorm.default.mapping = {
'user-type'(type: ZoneIdUserType, class: ZoneId)
}
Run Code Online (Sandbox Code Playgroud)
您可以在域类中简单地使用 java.time.ZoneId :
import java.time.ZoneId
class MyDomain {
ZoneId zoneId
}
Run Code Online (Sandbox Code Playgroud)
看:
| 归档时间: |
|
| 查看次数: |
757 次 |
| 最近记录: |