eclipse+JBoss5+EJB3开发指南(7)

实现Entity Bean的一对一(one-to-one)映射

一对一映射是很常用的。在一般情况下,一个主表通过外键和从表形成一对一的关系。在EJB3中使用 @OneToOne注释来映射。一对一关系除了使用外键进行关联外,也可以采用共享主键的方式连接两个表。 先看看如下两个表的结构:

图1  t_customers

图2  t_referees

t_customers和t_referees表形成了一对一的关系。t_customers表通过referee_id与t_referees表相 连。与t_customers表对应的实体Bean的代码如下:

package entity;import java.util.Collection;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.OneToOne;import javax.persistence.Table;@Entity@Table(name = "t_customers")public class Customer{    private int id;    private String name;    private Referee referee;    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    public int getId()    {        return id;    }    public void setId(int id)    {        this.id = id;    }    public String getName()    {        return name;    }    public void setName(String name)    {        this.name = name;    }    @OneToOne    public Referee getReferee()    {        return referee;    }    public void setReferee(Referee referee)    {        this.referee = referee;    }}

从上面的代码可以看出,getReferee方法使用了@OneToOne进行设置。在装载Customer对象的同时, Referee对象会被同时装载,而默认的外键字段就是Customer类中的referee属性名 + “_” + id,也就是 referee_id。下面看一下与t_referees表对应的实体Bean代码:

package entity;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.OneToOne;import javax.persistence.Table;@Entity@Table(name="t_referees")public class Referee{    private int id;    private String name;    private Customer customer;    @OneToOne(mappedBy="referee")    public Customer getCustomer()    {        return customer;    }    public void setCustomer(Customer customer)    {        this.customer = customer;    }    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    public int getId()    {        return id;    }    public void setId(int id)    {        this.id = id;    }    public String getName()    {        return name;    }    public void setName(String name)    {        this.name = name;    }}

Referee类使用了customer属性映射了Customer对象,实际上,这是一个双向的one-to-one映射。这时 ,在Referee类的customer属性的getter方法的@OneToOne注释中,需要使用mappedBy属性来指定主表 (Customer)中的映射从表的属性名(referee)。

我们可以使用下面的代码进行测试:

System.out.println(em.find(Referee.class, 1).getCustomer().getName());Customer customer = new Customer();customer.setName("微软");Referee referee = new Referee();referee.setName("赵军");em.persist(referee);customer.setReferee(referee);em.persist(customer);

如果要覆盖默认的名键名,例如,外键名为referee1_id,可以两种方法使EJB3容器使用新的外键:

1.  修改Customer类中的referee属性的getter和setter方法为getReferee1和setReferee1,并将 Referee类中mappedBy属性的值修改成referee1。

2.  使用@JoinColumn注释设置新的外键名,这种方法只需要修改Customer类的getReferee方法上面 注释即可,代码如下:

@OneToOne@JoinColumn(name="referee1_id")public Referee getReferee(){    return referee;}

one-to-one关系还可以共享主键,也就是一个表的主键的值依赖于另一个表的主键的值。因此,在这 种情况下,就不再需要t_customers表中的referee_id字段了。由于t_referees表的id字段值依赖于 t_customers表的id字段值,因此,需要将t_referees表中的id字段值的自增类型去掉。

在EJB3中使用@PrimaryKeyJoinColumn注释来实现主键的共享。首先需要修改Customer类的getReferee 方法上方的注释,修改后的代码如下:

@OneToOne(cascade=CascadeType.ALL)@PrimaryKeyJoinColumnpublic Referee getReferee(){    return referee;}

然后要修改Referee类中的getCustomer和getId方法上方的注释,修改后的代码如下:

@OneToOne@PrimaryKeyJoinColumnpublic Customer getCustomer(){    return customer;}@Id@GeneratedValue(generaTor = "pkGeneraTor")@GenericGeneraTor(name = "pkGeneraTor", strategy = "foreign",    parameters = @Parameter(name = "property", value = "customer"))public int getId(){    return id;}

其中@GenericGeneraTor注释表示这个id属性是外键,并且依赖于customer属性对应的实体Bean的id属 性值(主键值)。

另外还要注意一点,由于t_referees表的id的自增类型已经去掉,而且该值依赖于t_customers表的id 字段值,因此,就不能直接持久化Referee对象了,而在持久化Customer对象的同时,EJB3容器会自动将 Referee持久化的。

青春气贯长虹,勇敢盖过怯懦,进取压倒苟安。

eclipse+JBoss5+EJB3开发指南(7)

相关文章:

你感兴趣的文章:

标签云: