Hibernate参考手册学习与实践:持久化类

前言:使用Hibernate也有一段时间了,但总没时间好好看看它的细节。现在每天利用一点时间把Hibernate参考手册再好好学习一下,并摘要部分认为比较重要的内容。现在Hibernate已经有大把的资料,翻译参考手册并无太大的价值,本文纯粹是为了加深对Hibernate的理解而已,是写给自己看。


1. 持久化类

在Hibernate中,持久化类就是POJO(Plain Old Java Object)。虽然Hibernate对持久化类没有过多的限制,甚至使用Map实例也可以,但POJO还是最好最常用的方式。
一个表示cat的持久化类示例如下:

package eg;
import java.util.Set;
import java.util.Date;

public class Cat {
    private Long id; // identifier
    private Date birthdate;
    private Color color;
    private char sex;
    private float weight;
    private int litterId;

    private Cat mother;
    private Set kittens = new HashSet();

    private void setId(Long id) {
        this.xml:id=id;
    }
    public Long getId() {
        return id;
    }

    void setBirthdate(Date date) {
        birthdate = date;
    }
    public Date getBirthdate() {
        return birthdate;
    }

    void setWeight(float weight) {
        this.weight = weight;
    }
    public float getWeight() {
        return weight;
    }

    public Color getColor() {
        return color;
    }
    void setColor(Color color) {
        this.color = color;
    }

    void setSex(char sex) {
        this.sex=sex;
    }
    public char getSex() {
        return sex;
    }

    void setLitterId(int id) {
        this.litterId = id;
    }
    public int getLitterId() {
        return litterId;
    }

    void setMother(Cat mother) {
        this.mother = mother;
    }
    public Cat getMother() {
        return mother;
    }
    void setKittens(Set kittens) {
        this.kittens = kittens;
    }
    public Set getKittens() {
        return kittens;
    }

    // addKitten not needed by Hibernate
    public void addKitten(Cat kitten) {
        kitten.setMother(this);
    kitten.setLitterId( kittens.size() );
        kittens.add(kitten);
    }
}

1.1 持久化类的规则

持久化类主要以下四条主要规则:

  • 具有无参构造方法。上述Cat类就具有一个默认的无参构造方法。Hibernate是使用java.lang.reflect.Constructor.newInstance()来示例化持久化类的。为了使运行时proxy创建正确的工作,建议构造方法至少是包可见的。
  • 提供一个标识属性。在Cat类中就有一个名为id的标识属性,一般情况下它对应于相应数据库表的主键。也可以对应具有唯一标识的列。Hibernate建议标识属性使用类类型的数据类型,如Long,Integer等。
  • 持久化类最好是非final类。Hibernate的核心特征——proxies(lazy loading),就是依靠非final类或者是实现了共有方法的接口的类。除非你不想使用lazy loading,你才使用final类。
  • 对持久化域声明访问和赋值方法,即对需要持久化的属性需要有getter和setter方法。
    在hbm.xml中关闭proxies的方法:
<class name="Cat" lazy="false"...>...</class>

使用注解关闭proxies的方法:

@Entity @Proxy(lazy=false) public class Cat { ... }

1.2 持久化类的继承

持久化里的子类也遵从相同的规则。

1.3 实现equals()和hashCode()

如果你有一下操作,你必须重写equals()和hashCode()方法:
- 欲把持久化对象放在Set中。
- 欲将离线实例重新加载。
Hibernate能构造保证在一个session范围内持久化标识和Java标识保持一致。当你从不同session中获得混合实例,如果你还希望保持Set语义(Set中每个元素都不相同)的话,你就必须重写equals()和hashCode()方法。
建议使用Business key equality来实现equals()和hashCode()。如:

public class Cat {

    ...
    public boolean equals(Object other) {
        if (this == other) return true;
        if ( !(other instanceof Cat) ) return false;

        final Cat cat = (Cat) other;

        if ( !cat.getLitterId().equals( getLitterId() ) ) return false;
        if ( !cat.getMother().equals( getMother() ) ) return false;

        return true;
    }

    public int hashCode() {
        int result;
        result = getMother().hashCode();
        result = 29 * result + getLitterId();
        return result;
    }

}

1.4 动态模型

动态模型现在被认为是实验性的,有可能将来会发生变化。在这里略过。

1.5 Tuplizer

一个比较奇怪的词。从它的英文愿意理解,应该是负责持久化类创建、存取的类。一般情况下,我们不需要编写Tuplizer,除非你的持久化类很复杂,或者你想定义一个不同的proxy生成策略。可以通过注解或hbm.xml来为一个持久化类指定一个Tuplizer(具体略)。
在实践中常见的和Tuplizer相关的错误是持久化类的getter和setter没有正确编写。前些年和Tuplizer有关的错误是和Spring中的包冲突引起的问题。

1.6 EntityNameResolver

一般情况下我们也不需要实现org.hibernate.EntityNameResolver接口,它有一个唯一的方法resolveEntityName接受一个实体实例参数,它用于解析实体的名称。它通常和动态模型有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值