hibernate映射值类型

JDK基本类型

  • @Transient:用于将某个属性设为瞬时,其不会被映射到数据库,默认的所有属性都将映射到数据库
  • @Access:用于设置访问属性的策略,当值为@Access(AccessType.PROPERTY)时使用setter,否则使用field。可用于类/具体属性上
  • @Column:用于进行属性-列名映射以及指定约束(非空、唯一、是否可更新等)
  • @Formula:用于在query时,从数据库取值设置,对于update/save/insert无效
@org.hibernate.annotations.Formula("(select avg(b.AMOUNT) from BID b where b.ITEM_ID = ID)")
protected BigDecimal averageBidAmount;
  • @ColumnTransformer:用于进行实体属性存入/取出数据库的转换,在作为HQl查询时也会自动转换
@Column(name = "IMPERIALWEIGHT")
@org.hibernate.annotations.ColumnTransformer(
read = "IMPERIALWEIGHT / 2.20462",
write = "? * 2.20462"
)
protected double metricWeight;
  • @org.hibernate.annotations.Generated:自动生成属性,用户不应该指定
@Temporal(TemporalType.TIMESTAMP)
@Column(insertable = false, updatable = false)
@org.hibernate.annotations.Generated(
//永远使用最晚修改的时间
org.hibernate.annotations.GenerationTime.ALWAYS
)
protected Date lastModified;
  • @Temporal:精确控制时间
  • @Enumerated(EnumType.STRING):映射一个枚举类型
  • @Lob:用于映射大值类型,具体为String、char[] --> clob;serilizable、byte[] --> blob;byte[]默认不注解即映射到clob
  • java.util.Date保存后(save)再加载(get),将不再返回java.util.Date,而是java.sql.*,所以不再适合调用equals()比较,可以自定义转换器将java.sql.*转为java.util.Date

自定义值类型(@Embeddable取代@Entity,@Embedded+@AttributeOverrides取代@Column)

  • 多个自定义值类型可以使用@Embeded进行多级嵌入,甚至于可以不使用@Embedded
  • 当某个自定义嵌入的实例域X其对应的所有的属性均为null,则getX()将返回null,即setX(new X())不产生效果
  • @AttributeOverride(name="a.b.text",column = @Column()) ---> 多级重写属性

自定义类型转换器(类 -> 数据库)

  • JPA:实现AttributeConverter接口,缺点时只能映射到一列而且select * from i where i.monetaryamount.monry > 100将错误,因为整个monetaryamount映射成一个String
 //若未使用autoApply,可以在转换的具体实例域使用@Converte
 @Converter(autoApply = true)
 public class MonetaryAmountConverter implements AttributeConverter { 
      @Override
     public String convertToDatabaseColumn(MonetaryAmount monetaryAmount) { 
         return monetaryAmount.toString();
     } 
    @Override 
    public MonetaryAmount convertToEntityAttribute(String s) { 
        return MonetaryAmount.fromString(s);
     } 
} 
  • Hibernate实现:

//DynamicParameterizedType:(用于获得注解/表名等运行时参数)
public class DateUserType implements DynamicParameterizedType{
    @Override
    public void setParameterValues(Properties parameters) {
        //获得配置的表名/列名等信息
        ParameterType pt = (ParameterType) parameters.get(PARAMETER_TYPE);
        String table = pt.getTable();
        String[] columns = pt.getColumns();
        //获得传递的参数,使用@org.hibernate.annotations.TypeDef()的parameters设置
        String value = parameters.getProperty("parameterName");
    }
}
//CompositeUserType:用于实际加载、缓存控制对象等
public class DateUserType implements CompositeUserType{
    //最重要的两个方法,分别实现了从数据加载对象,和写对象到数据库。
    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
       if(rs.wasNull()){
            return null;
        }
        String firstField = rs.getString(names[0]);
        String secondField = rs.getString(names[1]);
        return new MyClass(firstField,secondField);
    }

    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
        st.setObject(index,value);
    }
    //按顺序返回实例域名
    @Override
    public String[] getPropertyNames() {
        return new String{"firstFieldName","secondFieldName"};
    }
    //按顺序返回映射到数据库的数据库类型
    @Override
    public Type[] getPropertyTypes() {
        return new Type[]{StandardBasicTypes.DATE,StandardBasicTypes.INT};
    }
    //获得对象对应的位置的属性值
    @Override
    public Object getPropertyValue(Object component, int property) throws HibernateException {
        MyClass mc = (MyClass)component;
        if(index == 0){
            return mc.getFistField();
        }else if(index == 1){
            return mc.getSecondField();
        }else{
            return null;
        }
    }
    //给对象对应位置的属性设置值
    @Override
    public void setPropertyValue(Object component, int property, Object value) throws HibernateException {
        if(value == null){
            st.setNull(index,StandardBasicTypes.CHARACTER.sqlType());
            st.setNull(index+1,StandardBasicTypes.CHARACTER.sqlType());
        }else{
            MyClass mc = (MyClass)value;
            st.setString(index,mc.getFisrtField());
            st.setString(index,mc.getSecondField());
        }
    }
    //自定义转换的类.class
    @Override
    public Class returnedClass() {
        return MyClass.class;
    }
    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        return false;
    }

    @Override
    public int hashCode(Object x) throws HibernateException {
        return 0;
    }

    @Override
    public Object deepCopy(Object value) throws HibernateException {
        return null;
    }

    @Override
    public boolean isMutable() {
        return true;
    }
    //以下两个方法用于二级缓存
    @Override
    public Serializable disassemble(Object value, SessionImplementor session) throws HibernateException {
        return (Serializable)value;
    }

    @Override
    public Object assemble(Serializable cached, SessionImplementor session, Object owner) throws HibernateException {
        return cached;
    }
    //用于merge,把target的更新属性拷贝至original
    @Override
    public Object replace(Object original, Object target, SessionImplementor session, Object owner) throws HibernateException {
        return null;
    }
}

使用时,在package-info.java中使用@TypeDef定义类型,并传入对应的参数。
在具体的实例域使用@Type进行使用
posted @ 2016-04-02 23:16  fcat  阅读(959)  评论(0编辑  收藏  举报