1 实体粒度划分的意义
在整个Hibernate技术应用之中,基本的流程:要提供有一个POJO类,而后要提供有一个POJO.hbm.xml文件,但是如果说现在假设有如下一种情况出现。
范例:定义数据库脚本
-- 删除数据表
DROP TABLE IF EXISTS 'member';
-- 创建数据表
CREATE TABLE 'member'(
mid VARCHAR(50),
mname VARCHAR(50),
mage INT,
mbirthday DATE,
maddress VARCHAR(100),
mzipcode VARCHAR(8),
mphone VARCHAR(50),
CONSTRAINT pk_nid PRIMARY KEY(nid)
);
如果按照正常的思路,那么此时生成的POJO类的结构如下。
范例:生成的POJO类的结构
public class Member implements java.io.Serializable {
// Fields
private String mid;
private String mname;
private Integer mage;
private Date mbirthday;
private String maddress;
private String mzipcode;
private String mphone;
}
有人现在会提出这样的问题,以上的设计方式不适合于面向对象的应用形式。从面向对象的角度来看以上的Member的组成应该分为:Member、MemberBasic、MemberContact。而每个类的作用如下:
(1)MemberBasic:
package org.lks.pojo;
import java.util.Date;
@SuppressWarnings("serial")
public class MemberBasic implements java.io.Serializable {
private String mname;
private Integer mage;
private Date mbirthday;
}
(2)MemberContract:
package org.lks.pojo;
@SuppressWarnings("serial")
public class MemberContact implements java.io.Serializable {
private String maddress;
private String mzipcode;
private String mphone;
}
(3)Member:
package org.lks.pojo;
@SuppressWarnings("serial")
public class Member implements java.io.Serializable {
private String mid;
private MemberBasic basic = new MemberBasic();
private MemberContact contact = new MemberContact();
}
此时的结构非常符合于面向对象的设计思想,这种的设计方式应该算是合成设计模式。
2 基于*.hbm.xml
文件实现细粒度划分
虽然现在只有一张member表,但是却发现有三个实体类,并且这些实体类之间是存有引用关系的,而要想使用Hibernate开发,就必须将这些关系再配置文件中进行展示。
所以现在的重点就在配置文件的编写上。
范例:在Member.hbm.xml文件中实现配置
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<!-- 不管如何操作,每一个*.hbm.xml文件只会与一个POJO类关联 -->
<class name="org.lks.pojo.Member" table="member" catalog="hedb">
<id name="mid" type="java.lang.String">
<column name="mid" length="50" />
<generator class="assigned"></generator>
</id>
<!-- 此处配置的Member类中的basic属性的类型以及包含的内容 -->
<component name="basic" class="org.lks.pojo.MemberBasic">
<property name="mname" type="java.lang.String">
<column name="mname" length="50" />
</property>
<property name="mage" type="java.lang.Integer">
<column name="mage" />
</property>
<property name="mbirthday" type="java.util.Date">
<column name="mbirthday" length="10" />
</property>
</component>
<!-- 此处配置的Member类中的contact属性的类型以及包含的内容 -->
<component name="contact" class="org.lks.pojo.MemberContact">
<property name="maddress" type="java.lang.String">
<column name="maddress" length="100" />
</property>
<property name="mzipcode" type="java.lang.String">
<column name="mzipcode" length="8" />
</property>
<property name="mphone" type="java.lang.String">
<column name="mphone" length="50" />
</property>
</component>
</class>
</hibernate-mapping>
配置完成之后下面直接使用程序进行测试。
范例:编写增加操作
package org.lks.test;
import java.text.SimpleDateFormat;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;
public class TestMemberInsert {
public static void main(String[] args) throws Exception {
Member vo = new Member();
vo.setMid("3161301220");
vo.getBasic().setMage(23);
vo.getBasic().setMname("lks");
vo.getBasic().setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1996-10-15"));
vo.getContact().setMaddress("河南");
vo.getContact().setMphone("121291");
vo.getContact().setMzipcode("237283");
HibernateSessionFactory.getSession().save(vo);
HibernateSessionFactory.getSession().beginTransaction().commit();
HibernateSessionFactory.closeSession();
System.exit(0);
}
}
Hibernate:
insert into
hedb.member (mname, mage, mbirthday, maddress, mzipcode, mphone, mid)
values (?, ?, ?, ?, ?, ?, ?)
现在虽然是属于不同的类型,但是在最终生成的时候还是使用了一条SQL语句执行的增加。
范例:数据读取
package org.lks.test;
import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;
public class TestMemberGet {
public static void main(String[] args) throws Exception {
Member vo = (Member)HibernateSessionFactory.getSession().get(Member.class, "3161301220");
System.out.println(vo);
HibernateSessionFactory.closeSession();
System.exit(0);
}
}
Hibernate:
select
member0_.mid as mid1_0_0_,
member0_.mname as mname2_0_0_,
member0_.mage as mage3_0_0_,
member0_.mbirthday as mbirthda4_0_0_,
member0_.maddress as maddress5_0_0_,
member0_.mzipcode as mzipcode6_0_0_,
member0_.mphone as mphone7_0_0_
from
hedb.member member0_
where
member0_.mid=?
Member [mid=3161301220, basic=MemberBasic [mname=lks, mage=23, mbirthday=1996-10-14 08:00:00.0], contact=MemberContact [maddress=河南, mzipcode=237283, mphone=121291]]
此时依然只发出了一条查询指令,但是查询之后的数据都已经各自保存到各自对象之中。
3 基于Annotation的配置
如果真的要使用了实体的细粒度划分,那么还是HBM的配置方式简便,而Annotation的配置模式太麻烦了。
首先还是生成一个基于Annotation配置的Member类,但是随后需要对这些类进行修改。
范例:创建支持于Annotation配置的MemberBasic类
package org.lks.pojo;
import java.util.Date;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@SuppressWarnings("serial")
@Embeddable
@AttributeOverrides({
@AttributeOverride(name="mname",column=@Column(name="mname")),
@AttributeOverride(name="mage",column=@Column(name="mage")),
@AttributeOverride(name="mbirthday",column=@Column(name="mbirthday"))
})
public class MemberBasic implements java.io.Serializable {
private String mname;
private Integer mage;
private Date mbirthday;
@Column(name = "mname", length = 50)
public String getMname() {
return this.mname;
}
public void setMname(String mname) {
this.mname = mname;
}
@Column(name = "mage")
public Integer getMage() {
return this.mage;
}
public void setMage(Integer mage) {
this.mage = mage;
}
@Temporal(TemporalType.DATE)
@Column(name = "mbirthday", length = 10)
public Date getMbirthday() {
return this.mbirthday;
}
public void setMbirthday(Date mbirthday) {
this.mbirthday = mbirthday;
}
}
范例:创建支持于Annotation配置的MemberContact类
package org.lks.pojo;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embeddable;
@SuppressWarnings("serial")
@Embeddable
@AttributeOverrides({
@AttributeOverride(name="maddress",column=@Column(name="maddress")),
@AttributeOverride(name="mzipcode",column=@Column(name="mzipcode")),
@AttributeOverride(name="mphone",column=@Column(name="mphone")),
})
public class MemberContact implements java.io.Serializable {
private String maddress;
private String mzipcode;
private String mphone;
@Column(name = "maddress", length = 100)
public String getMaddress() {
return this.maddress;
}
public void setMaddress(String maddress) {
this.maddress = maddress;
}
@Column(name = "mzipcode", length = 8)
public String getMzipcode() {
return this.mzipcode;
}
public void setMzipcode(String mzipcode) {
this.mzipcode = mzipcode;
}
@Column(name = "mphone", length = 50)
public String getMphone() {
return this.mphone;
}
public void setMphone(String mphone) {
this.mphone = mphone;
}
}
范例:修改Member类定义
package org.lks.pojo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name = "member", catalog = "hedb")
public class Member implements java.io.Serializable {
// Fields
private String mid;
private MemberBasic basic = new MemberBasic();
private MemberContact contact = new MemberContact();
@Id
@Column(name = "mid", unique = true, nullable = false, length = 50)
public String getMid() {
return this.mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public MemberBasic getBasic() {
return basic;
}
public void setBasic(MemberBasic basic) {
this.basic = basic;
}
public MemberContact getContact() {
return contact;
}
public void setContact(MemberContact contact) {
this.contact = contact;
}
}
此处关键就在于被包含的细粒度类上的变化。