2015-03-30 37 views
0

我想知道hibernate是否对特定类型的类实施任何限制来保持它们。我读过Hibernate可以坚持JavaBean类和Pojos。什么类型的Hibernate可以持续存在?

这是否意味着hibernate不能坚持不属于这两类的类?

我们可以在hibernate中坚持非pojo类吗? e.g

Class A extends B{} 

基本上我需要知道是什么让冬眠无法坚持一类在RDBMS?

回答

2

持久类是实现业务问题实体(例如电子商务应用程序中的客户和订单)的应用程序中的类。并非所有持久类的实例都被认为处于持久状态。例如,一个实例可以是暂时的或分离的。

如果这些类遵循一些简单规则(也称为普通旧Java对象(PO​​JO)编程模型),则Hibernate最为有效。但是,这些规则都不是硬性要求。事实上,Hibernate3对持久对象的性质的假设很少。您可以用其他方式表示域模型(例如,使用Map实例的树)。

大多数Java应用程序需要一个代表猫的持久类。例如:

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.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.Implement一个无参数的构造函数

Cat有一个无参数的构造函数。所有的持久化类必须有一个默认的构造函数(可以是非公有的),这样Hibernate可以使用Constructor.newInstance()来实例化它们。建议您有一个默认的构造函数,至少在Hibernate中为包运行时代理生成包可见性。 2.2。提供标识符属性(可选)

Cat有一个名为id的属性。该属性映射到数据库表的主键列。该属性可能被称为任何东西,其类型可能是任何原始类型,任何原始的“包装”类型,java.lang.String或java.util.Date。如果您的旧数据库表具有组合键,则可以使用具有这些类型属性的用户定义类(请参阅本章后面的组合标识符一节。)

标识符属性是严格可选的。您可以将它们关闭,让Hibernate在内部跟踪对象标识符。但是,我们不建议这样做。

实际上,一些功能只对那些声明了标识符属性的类:

传递复位对脱管对象(级联更新或级联合并) - 见10.11,“传递坚持” Session.saveOrUpdate( ) Session.merge() 我们建议您在持久化类上声明一致命名的标识符属性,并且使用可空(即非基元)类型。

  • 体型非最终类(可选)
  • Hibernate的一个重要特征,代理服务器,取决于持久化类或者非最终,或执行一个声明所有公共方法的接口。

    您可以坚持不使用Hibernate实现接口的最终类​​。但是,您不能使用代理进行惰性关联抓取,这最终会限制您的性能调整选项。

    您还应该避免在非最终类上声明公共最终方法。如果你想使用一个具有public final方法的类,你必须通过设置lazy =“false”来显式地禁用代理。

  • 申报accessor和mutator为持久字段(可选)
  • 猫声明其所有持久字段访问方法。许多其他ORM工具直接持久化实例变量。提供关系模式和类的内部数据结构之间的间接性更好。默认情况下,Hibernate持久化JavaBeans样式属性并识别getFoo,isFoo和setFoo形式的方法名称。如果需要,您可以切换到特定属性的直接字段访问。

    属性不需要声明为公共--Hibernate可以使用默认的,受保护的或私有的get/set对来持久化属性。

    实现继承

    子类也必须遵守第一条和第二条规则。它从超类Cat继承它的标识符属性。例如:

    package eg;如果你

    public class DomesticCat extends Cat { 
        private String name; 
    
        public String getName() { 
          return name; 
        } 
        protected void setName(String name) { 
          this.name=name; 
        } 
        } 
    

    实现equals()和hashCode()

    你必须重载equals()和hashCode()方法:

    想把持久类的实例放入Set(推荐的方式来表示多值协会);和 打算使用重新连接的分离实例 Hibernate保证只在特定会话范围内保持持久性标识(数据库行)和Java标识的等同性。当您混合使用不同会话检索到的实例时,如果您希望为集合提供有意义的语义,则必须实现equals()和hashCode()。

    最明显的方法是通过比较两个对象的标识符值来实现equals()/ hashCode()。如果值相同,则两者必须是相同的数据库行,因为它们相同。如果两者都添加到Set中,则只有Set中有一个元素)。不幸的是,你不能在生成的标识符中使用这种方法。 Hibernate只会将标识符值分配给持久对象;新创建的实例将不具有任何标识符值。此外,如果实例未保存且当前位于Set中,则保存该实例将为该对象分配一个标识符值。如果equals()和hashCode()基于标识符值,那么哈希码将发生变化,从而破坏Set的契约。有关此问题的完整讨论,请参阅Hibernate网站。这不是Hibernate问题,而是对象身份和相等性的普通Java语义。

    建议您使用业务键相等来实现equals()和hashCode()。业务密钥相等意味着equals()方法仅比较构成业务密钥的属性。这是一个关键,将确定在现实世界中我们的实例(自然的候选键):

    公共类猫{

    ... 
    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; 
    } 
    

    } 业务键不必像数据库为固体主键候选者不可变或独特的属性通常是业务键的良好候选者。

    +0

    当复制/粘贴参考文档即https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/persistent-classes.html时,对资源进行记录很有用。 – grid 2015-04-01 16:42:30

    0

    从实践我知道对象硬要这样的限制:

    1. 标有@Entity只有类可以坚持,但不是所有的超类必须有这样的注解。
    2. 您不能在实体中为字段类型使用接口或非实体类(用于持久目的)。
    3. 这就是为什么你不能在实体中使用泛型的全部力量。

    在现实世界中,pojo和java beans并不全是你需要的,并且希望成功的工作。

    相关问题