最近,我想为商人建模,就像域模型中的许多事物都有一个地址一样。 我认为将地址嵌入到商家中是有道理的。 原因:
- 它在商人之外没有生命周期。 商家死亡,地址也应死亡。
- 它只属于一个商人
很明显,这是一个构图关系。
现在,可以在GORM中对组成关系建模。 看这里 。 但是,这种方法带有以下警告:地址必须是GORM对象。 我不希望该地址成为GORM对象,因为GORM对象在Grails中功能强大。 凭借其所有动态查找器和GORM API,它们本质上就像是类固醇上的DAO。 如果开发人员可以动手,他们可以做很多事情(并非总是好事)。 我不需要或不需要任何这些。 此外,良好的体系结构使开发人员在压力下以快速运行时难以犯错。 这意味着,在制定设计决策时,您需要考虑需要给予,应该给予和将会给予的力量。
因此,考虑到这一点,我研究了为Address连接自定义类型的方法。 这只是一个可以对地址进行建模的数据结构,可以在商家外部重用(从而提高一致性,从而又可以促进良好的设计),而不会随GORM一起提供。 GORM文档中有一些有关自定义类型的文档,但是没有完整的示例。 我看了一些Hibernate示例,然后设法将它们放在一起并开始工作。
这是我的地址对象。
@Immutable
class Address {
private final String city;
private final String country;
private final String state;
private final String street1;
private final String street2;
private final String street3;
private final String zip;
public String getCity() {
return city;
}
public String getCountry() {
return country;
}
public String getZip() {
return zip;
}
public String getState() {
return state;
}
public String getStreet1() {
return street1;
}
public String getStreet2() {
return street2;
}
public String getStreet3() {
return street3;
}
}
这是我的AddressUserType对象:
class AddressUserType implements UserType {
public int[] sqlTypes() {
return [
StringType.INSTANCE.sqlType(),
StringType.INSTANCE.sqlType(),
StringType.INSTANCE.sqlType(),
StringType.INSTANCE.sqlType(),
StringType.INSTANCE.sqlType(),
StringType.INSTANCE.sqlType(),
StringType.INSTANCE.sqlType()
] as int[]
}
public Class getReturnedClass() {
return Address.class;
}
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws SQLException {
assert names.length == 7;
log.debug(">>mullSafeGet(name=${names}")
String city = StringType.INSTANCE.get(rs, names[0], session); // already handles null check
String country = StringType.INSTANCE.get(rs, names[1], session ); // already handles null check
String state = StringType.INSTANCE.get(rs, names[2], session ); // already handles null check
String street1 = StringType.INSTANCE.get(rs, names[3], session ); // already handles null check
String street2 = StringType.INSTANCE.get(rs, names[4], session ); // already handles null check
String street3 = StringType.INSTANCE.get(rs, names[5], session ); // already handles null check
String zip = StringType.INSTANCE.get(rs, names[6], session ); // already handles null check
return city == null && v == null ? null : new GAddress(city: city, country: country, state: state, street1: street1, street2: street2, street3: street3, zip: zip);
}
void nullSafeSet(java.sql.PreparedStatement st, java.lang.Object value, int index, org.hibernate.engine.spi.SessionImplementor session) throws org.hibernate.HibernateException, java.sql.SQLException {
if ( value == null ) {
StringType.INSTANCE.set( st, null, index );
StringType.INSTANCE.set( st, null, index+1 );
StringType.INSTANCE.set( st, null, index+2 );
StringType.INSTANCE.set( st, null, index+3 );
StringType.INSTANCE.set( st, null, index+4 );
StringType.INSTANCE.set( st, null, index+5 );
StringType.INSTANCE.set( st, null, index+6 );
}
else {
final Address address = (Address) value;
StringType.INSTANCE.set( st, address.getCity(), index,session );
StringType.INSTANCE.set( st, address.getCountry(), index+1,session);
StringType.INSTANCE.set( st, address.getState(), index+2,session);
StringType.INSTANCE.set( st, address.getStreet1(), index+3,session);
StringType.INSTANCE.set( st, address.getStreet2(), index+4,session);
StringType.INSTANCE.set( st, address.getStreet3(), index+5,session);
StringType.INSTANCE.set( st, address.getZip(), index+6,session);
}
}
@Override
public boolean isMutable() {
return false;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
// for now
return x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
assert (x != null);
return x.hashCode();
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return original;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
public Class returnedClass() {
return Address.class;
}
}
这是我的商人,里面有一个地址。
class Merchant {
UUID id;
String color;
String displayName;
//...
//...
Address address
static mapping = {
address type: AddressUserType, {
column name: "city"
column name: "country"
column name: "zip"
column name: "state"
column name: "street1"
column name: "street2"
column name: "street3"
}
}
}
如上所述,通过这种方法,可以在其他GORM对象中使用Address数据结构。 直到下一次照顾自己。
翻译自: https://www.javacodegeeks.com/2015/09/custom-user-types-in-gorm.html