Hibernate实战_笔记17(持久化实体类)(一)

2014-11-24 01:25:14 · 作者: · 浏览: 3

编写POJO和持久化实体类

Hibernate与用POJO实现的领域模型合作得最好。Hibernate强加给领域模型实现的少数必备条件,对于POJO实现也是最佳实践,因此大部分POJO不用任何改变就可以与Hibernate兼容。Hibernate的必备条件几乎与EJB3.0实体类的相同,因此POJO实现可以轻松地用注解标识,并创造一个EJB3.0兼容的实体。
POJO声明了定义行为的业务方法和表示状态的属性。有些属性表示与其他用户自定义的POJO的关联。
User类的POJO实现
public class User implements Serializable {
	private static final long serialVersionUID = -7811634244303955773L;


	private String username;
	private Address address;


	public User() {
		super();
	}


	public User(String username, Address address) {
		super();
		this.username = username;
		this.address = address;
	}


	public String getUsername() {
		return username;
	}


	public void setUsername(String username) {
		this.username = username;
	}


	public Address getAddress() {
		return address;
	}


	public void setAddress(Address address) {
		this.address = address;
	}
	
	// 计算价格
	public MonetaryAmount calcShippingCosts(Address fromLocation) {
		return null;
	}
}
Hibernate不要求持久化类实现Serializable(可序列化)。然而,当对象被存储在一个HttpSession中,或者用RMI按值传递时,就需要序列化。类可以是抽象的,必要时,可以扩展非持久化的类。
不同于JavaBeans规范,它不需要特定的构造函数,而Hibernate(和JPA)则要求每个持久化类都有个无参构造函数。Hibernate在这个构造函数上使用Java Reflection API调用持久化类来实例化对象。构造函数可以是非公共的,但必须至少是包可见(package-visible)的,如果运行时代理要用于性能优化的话。代理生成也要求这个类不作final声明(也没有final方法)。
JavaBean规范定义了命名这些方法的指导方针,允许普通的工具(如Hibernate)轻松地发现和操作属性值。获取方法的名称以get开头,接着是属性名称(首字母大写);设置方法的名称以set开关,并且类似地也跟着属性名称。用于Boolean属性的获取方法可以用Is而不是Get。
实现POJO关联
你用属性表达POJO类之间的关联,并用访问方法在运行时从一个对象到一个对象进行导航。
考虑由Category类定义的那些关联,如图3-3所示。
和所有的图一样,上图省略了与关联相关的属性(我们称之为parentCategory和childCategories),因为它们会把图弄乱。操作它们值的这些属性和方法也称作脚手架代码(scaffolding code)。
这是一个Category类一对多自关联的脚手架代码:
public class Category {
	private String name;// 类型名称
	private Category parentCategory;// 父类型
	private Set
  
    childCategories = new HashSet
   
    ();// 子类型 public Category() { super(); } public Category(String name, Category parentCategory, Set
    
      childCategories) { super(); this.name = name; this.parentCategory = parentCategory; this.childCategories = childCategories; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Category getParentCategory() { return parentCategory; } public void setParentCategory(Category parentCategory) { this.parentCategory = parentCategory; } public Set
     
       getChildCategories() { return childCategories; } public void setChildCategories(Set
      
        childCategories) { this.childCategories = childCategories; } }
      
     
    
   
  
管理两个Category实例之间的链接,比在数据库字段中设置外键值更难。依据我们的经验,开发人员经常不知道从一个包含双向引用的网络对象模型中所产生的这种复杂性。我们将一步一步地探讨这个问题。
把一个子Category添加给一个父Category的基本过程看起来像这样:
Category aParent = new Category();
Category aChild = new Category();
aChild.setParentCategory(aParent);
aParent.getChildCategories().add(aChild);
说明:Hibernate中的托管关系――Hibernate不管理持久化关联。如果你要操作一个关联,必须编写与没有Hibernate时要编写完全相同的代码。如果关联是双向的,则关系的两侧都必须考虑。 编程模型(如EJB2.1实体bean)通过引入容器托管的关系扰乱了这个行为――如果一侧被应用程序修改,容器就会自动改变关系的另一侧。这就是为什么使用EJB2.1实体bean的代码不能在容器之外被重用的原因之一。EJB3.0关联是透明的,就像在Hibernate中一样。如果你不理解Hibernate中关联的这种行为,就问问你自己:“没有Hibernate时我会怎么做?”Hibernate不会改变一般的Java语义。
给这些操作进行分组的Category类添加一种方便的方法是个好主意,这样允许重用,帮助确保正确性,并且最终保证数据的完整性:
public void addChildCategory(Category childCategory) {
		if (null == childCategory)
			throw new IllegalArgumentException("Null child c