基础数据类型,如String、Integer、Date、Boolean等它们可以很方便的映射到数据库:
import grails.persistence.Entity @Entity class MyEntity { String code String name static constraints = { code(unique: true, minSize: 4, maxSize: 4) name(blank: false, maxSize: 255) } }
这些基础数据类型是JAVA提供的语言级的,它没有语意。
比如要表达一个身份证号码:它有长度限制:15位或18位;还有规则限制;还能从身份证号码中提取出地址、性别、出生日期、年龄等信息。这些信息用一个String是无法表达,需要用类来描述:
class IDNumber{ String idNumber Address address InsDate birthday Gender gender IDNumber() {} IDNumber(val) { if (val.length() == 15) { val = to18IdNumber(val) } if (val.length() != 18) { throw new IllegalArgumentException("不是身份证格式") } this.idNumber = val return } def getAddress() { if (address) return address else return address = parseAddress() } def getBirthday() { if (birthday) return birthday else return birthday = parseBirth() } def getGender() { if (gender) return gender else return gender = parseGender() } def parseBirth() { ... } }
这个类里面最核心的就是String idNumber身份证号码,其他属性都是暂存的临时数据,可以从身份证号码里解析出来。如果想把这个类映射到数据库中,现在只能映射成一个table,但映射成table又不合理,最好是能映射成一列:
@grails.persistence.Entity
class PersonInfo {
String name
IDNumber idNumber
}
现在这样显然是不能达到这个目标的。
Hibernate提供了多种实现自定义类型的方法:
1、实现org.hibernate.usertype.UserType
2、实现org.hibernate.usertype.CompositeUserType
3、实现org.hibernate.usertype.UserCollectionType
4、实现org.hibernate.usertype.EnhanceUserType
通过实现这些接口,可以将自定义数据类型映射成数据库列。
UserType可以映射成单列,CompositeUserType可以映射成多列。
看个例子:
class MyString extends InsDataType implements UserType{ String value @Override void buildData(val) { if (val instanceof MyString) { value = val.value return } if (val == null) value = null else if (val instanceof String) value = val else if (val instanceof Number) value = String.valueOf(val) else value = val.toString() return } static MyString from(val) { if (val instanceof MyString) return val MyString data = new MyString() data.build(val) return data } public String toString() { return value } int[] sqlTypes() { return [Types.VARCHAR] } Class returnedClass() { return MyString } boolean equals(Object x, Object y) { MyString mx, my if (x instanceof String) mx = MyString.from(x) if (x instanceof MyString) mx = x if (y instanceof String) my = MyString.from(y) if (y instanceof MyString) my = y if (mx?.value == my?.value) return true return false } int hashCode(Object x) { return ((MyString) x)?.value?.hashCode() } Object nullSafeGet(ResultSet rs, String[] names, Object owner) { if (rs.wasNull()) return null // String stringFromDb = (String) Hibernate.STRING.nullSafeGet(rs, names[0]); String stringFromDb = rs.getString(names[0]);