`
stenlylee
  • 浏览: 261564 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

用@SecondaryTable实现多表联合到一个实体

阅读更多

有时候你可能会想要在一个entity里面用到存储在两个表中的数据。你只需要一个entity类,不过数据是分开存储在两张表里面的,这种情况在处理遗留数据库的时候尤为多见。JPA允许你在一个entity类里面使用到一个以上表的数据,对应的注解为@javax.persistence.SecondaryTable。客户类里面有个属性用来存储客户的地址,不过相关的地址数据却是存储在另外一个表里面的。这两张表的结构为:

create table CUSTOMER_TABLE 

(
     CUST_ID integer Primary Key Not Null,
     FIRST_NAME varchar(20) not null,
     LAST_NAME varchar(50) not null
);

create table ADDRESS_TABLE 

(
    ADDRESS_ID integer primary key not null,
    STREET varchar(255) not null,
    CITY varchar(255) not null,
    STATE varchar(255) not null
);

 

想要使用@SecondaryTable注解,那么ADDRESS_TABLE的主键列必须与CUSTOMER_TABLE中的一列或多列有关联。

public @interface SecondaryTable
{
    String name( );
    String catalog( ) default "";
    String schema( ) default "";
    PrimaryKeyJoinColumn[] pkJoinColumns( ) default {};
    UniqueConstraint[] uniqueConstraints( ) default {};
}

public @interface PrimaryKeyJoinColumn
{
    String name( ) default "";
    String referencedColumnName( ) default "";
    String columnDefinition( ) default "";
}

 

@SecondaryTable一眼看上去与@Table注解很像,只是多了一个pkJoinColumns( )属性。在客户类中,你需要加上这个注解,并且使用嵌入式注解@PrimaryKeyJoinColumn来将ADDRESS_TABLE表的主键标注出来。@PrimaryKeyJoinColumn注解的name属性用来指定在当前关联中用来维护关系的列。referencedColumnName属性指定了CUSTOMER_TABLE表中用来与ADDRESS_TABLE表关联的列。

package com.titan.domain;

import javax.persistence.*;
import com.acme.imaging.JPEG;

@Entity
@Table(name="CUSTOMER_TABLE")
@SecondaryTable(name="ADDRESS_TABLE",
                 pkJoinColumns={
                    @PrimaryKeyJoinColumn(name="ADDRESS_ID")}) 

public class Customer implements java.io.Serializable {
...

 

@PrimaryKeyJoinColumn指明了ADDRESS_TABLE表中与CUSTOMER _TABLE表的主键关联的列。在这里,我们使用的是ADDRESS_ID。我们这里没有明确指定referencedColumnName属性的值,因为它会自动使用客户类的主键列。

 

下一步,我们来关联ADDRESS_TABLE表中的street、city、state列。如果你仔细看过@Column注解,那么你可能会记得,里面有个属性我们不常用到,就是table,我们使用这个属性来将地址相关的属性映射到其他表中:

package com.titan.domain;

import javax.persistence.*;
import com.acme.imaging.JPEG;

@Entity
@Table(name="CUSTOMER_TABLE")
@SecondaryTable(name="ADDRESS_TABLE",
                 pkJoinColumns={
                    @PrimaryKeyJoinColumn(name="ADDRESS_ID")})
public class Customer implements java.io.Serializable {
    private long id;
    private String firstName;
    private String lastName;
    private String street;
    private String city;
    private String state;
...
@Column(name="STREET", table="ADDRESS_TABLE")
    public String getStreet( ) { return street; }
    public void setStreet(String street) { this.street = street; }

@Column(name="CITY", table="ADDRESS_TABLE")
    public String getCity( ) { return city; }
    public void setCity(String city) { this.city = city; }

@Column(name="STATE", table="ADDRESS_TABLE")
    public String getState( ) { return state; }
    public void setState(String state) { this.state = state; }
...

 

接下来你可能会要问,如果我需要在这里映射超过两张表,该怎么办?比如你想要嵌入信用卡信息,但是信用卡信息又是存储在另外一张表中了。这里我们就要用到@SecondaryTables注解了。

package com.titan.domain;

import javax.persistence.*;
import com.acme.imaging.JPEG;

@Entity
@Table(name="CUSTOMER_TABLE")
@SecondaryTables({
     @SecondaryTable(name="ADDRESS_TABLE",
            pkJoinColumns={@PrimaryKeyJoinColumn (name="ADDRESS_ID")}),
     @SecondaryTable(name="CREDIT_CARD_TABLE",
            pkJoinColumns={@PrimaryKeyJoinColumn (name="CC_ID")})
})
public class Customer

 

然后你就可以将相关的属性通过@Column.table来指定了。

 

最后我们来看一下在xml配置文件里面,我们该如何写:

<entity-mappings>
    <entity class="com.titan.domain.Customer" access="PROPERTY">
       <table name="CUSTOMER_TABLE"/>
    <secondary-table name="ADDRESS_TABLE">
          <primary-key-join-column name="ADDRESS_ID"/>
       </secondary-table>
       <secondary-table name="CREDIT_CARD_TABLE">
          <primary-key-join-column name="CC_ID"/>
       </secondary-table>
       <attributes>
          <id name="id">
             <generated-value/>
          </id>
          <basic name="street">
             <column name="STREET" table="ADDRESS_TABLE"/>
          </basic>
...
       </attributes>
    </entity>
</entity-mappings>

 

<secondary-table>可以在<entity>内被多次定义。<primary-key-join-column>标签为<secondary-table>标签的子标签,其属性有name、referenced-column-name、column-definition。我们使用<column>标签的table属性来指定某一列是否存储在其他表中。

分享到:
评论
1 楼 xuhuan1108 2014-12-22  
请问必须都是主键吗?

@PrimaryKeyJoinColumn指明了ADDRESS_TABLE表中与CUSTOMER_TABLE表的主键关联的列。在这里,我们使用的是ADDRESS_ID。我们这里没有明确指定referencedColumnName属性的值,因为它会自动使用客户类的主键列。

CUSTOMER_TABLE表的主键CUST_ID是ADDRESS_TABLE表的主键ADDRESS_ID的外键?

相关推荐

    java程序使用JPA注解详解.doc

    * value:定义一个 SecondaryTable 数组,指定每个从表的属性 例如: ```java @Table(name = "CUSTOMER") @SecondaryTables( value = { @SecondaryTable(name = "CUST_NAME", pkJoin = { @PrimaryKeyJoinColumn...

    hibernate-bug-1:演示在将@MapKey与映射到@SecondaryTable的目标属性一起使用时在Hibernate中的错误

    而@SecondaryTable则用于将一个类映射到多个数据库表,当一个实体的数据无法全部存放在一个表中时,我们可以通过这个注解将部分字段映射到第二个或更多的表。这通常发生在需要扩展表结构或者有大量数据需要拆分的...

    2022年EJB 3.0开发指南之多表映射Java教程.docx

    如果一个实体Bean需要映射到多个表,可以使用`@SecondaryTables`注解,它接受一个`SecondaryTable`数组,这样就可以声明多个次级表。例如: ```java @Entity @Table(name = "STUDENT") @SecondaryTables({ @...

    java程序使用JPA注解详解

    * value:定义一个 SecondaryTable 数组,指定每个从表的属性 例如: ```java @Table(name = "CUSTOMER") @SecondaryTables( value = { @SecondaryTable(name = "CUST_NAME", pkJoin = { @PrimaryKeyJoinColumn...

    Hibernate4之JPA规范配置详解

    当实体需要映射到多个表时,`@SecondaryTable` 用于定义实体类的从表信息。主表和从表之间的关系通常是通过主键进行关联。 - **name**:指定从表的名称。 - **catalog**:定义从表所在的数据库目录。 - **...

    hibernate 4 注解详解

    3. **@SecondaryTable**: 当一个实体类需要映射到多个表时,使用此注解。例如,`@SecondaryTable(name="CUST_DETAIL", pkJoin=@PrimaryKeyJoinColumn(name="CUST_ID"))` 表示实体类的辅助表 "CUST_DETAIL",其主键列...

    annotation实现hibernate

    3. `@SecondaryTable`和`@SecondaryTables`: 这两个注解用于表示一个实体类可以映射到不止一个表,`@SecondaryTable`用于单一从表,而`@SecondaryTables`用于多个从表。例如,`Customer`类可能同时映射到`CUSTOMER`...

    JPA注解参考手册.doc

    2. `@SecondaryTable`:这个注解用于表示一个实体类可以映射到多个表,其中一个为主表,其他为从表。例如: ```java @Entity @Table(name="CUSTOMER") @SecondaryTable(name="CUST_DETAIL", pkJoin=@...

    jpa常用标注

    2. **@SecondaryTable** 和 **@SecondaryTables**: 当一个实体需要映射到多个表时,这两个注解就派上用场了。`@SecondaryTable`用于定义单个从表,而`@SecondaryTables`则用于定义多个从表。`name`属性用于指定从表...

    JPA 批注参考 EJB3.0实体Bean注解详细解析

    15. **@SecondaryTable** - 用于指定一个实体映射到多个表时,除了主表之外的辅助表。 #### 三、配置实体的示例 - 使用 `@Entity` 和 `@Table` 批注定义实体和数据库表的映射关系。 - 使用 `@Id` 和 `@...

    jpa注解详解

    使用@Id、@IdClass、@EmbeddedId、@GeneratedValue、@SequenceGenerator、@TableGenerator批注可以指定以下项之一:一个@Id、多个@Id和一个@IdClass、一个@EmbeddedId,还可以使用这些批注微调数据库维护实体身份的...

    hibernate注解详解[参照].pdf

    3. **@SecondaryTable** 和 **@SecondaryTables**: 这些注解允许一个实体类映射到多个表,主表和一个或多个从表。`@SecondaryTable`用于定义单个从表,而`@SecondaryTables`用于定义多个从表。它们都包含`name`属性...

    EJB 3.0开发指南之多表映射

    事实上,一个实体Bean可以映射到多张表上。在一些需要字典表的项目上会经常用到,象以前我做过的项目,使用到很多国标规定的数据表。在我们下面这个例子中,性别作为一个字典表存在,学生这个实体将映射到学生信息表...

    JPA注解详解

    3. **@SecondaryTable**: 当一个实体需要被持久化到多个表时,可以使用这个注解。它允许将实体的一部分字段存储在主表(通过@Table注解指定),而其他字段存储在辅助表中。 ```java @Entity @Table(name=...

    hibernate注解.rar

    当一个实体需要映射到多个表时,可以使用@SecondaryTable注解。 3.3 @Temporal 对于日期和时间类型的字段,@Temporal注解可以指定存储格式,如TIMESTAMP、DATE或TIME。 3.4 @JoinColumn @JoinColumn用于指定实体间...

    hibernate注解详解说明

    通过 `@SecondaryTable` 注解可以将一个实体映射到多个表,常用于分离数据结构。 #### 映射查询 - `@NamedQuery` 和 `@NamedNativeQuery` 用于定义预编译的 HQL 或 SQL 查询,提高性能。 - `@Query` 注解允许在...

    JAP注解参考

    - `@SecondaryTable`和`@SecondaryTables`:当一个实体需要映射到多个表时使用。 2. **数据库模式属性**: - `@Column`:定义字段对应的数据库列名和属性。 - `@JoinColumn`和`@JoinColumns`:用于建立实体间的...

    jpa批注参考

    例如,`@Embeddable`和`@Embedded`用于标记一个实体作为另一个实体的嵌入式属性;`@AttributeOverride`和`@AttributeOverrides`用于覆盖嵌入式实体中属性的映射细节;`@AssociationOverride`和`@...

    JPA 批注总结参考

    1. **实体批注 (@Entity)**:用于标记一个Java类为JPA实体,这意味着这个类的实例可以被持久化到数据库。没有@Entity注解的类默认被认为是不可持久化的。 2. **数据库模式属性批注**: - `@Table`:定义实体所对应...

    jpa 批注参考 doc 格式 提供了一个对象关系映射方法

    - `@SecondaryTable`、`@SecondaryTables`:用于将一个实体映射到多个表。 - `@Column`:定义实体属性如何映射到数据库列。 - `@JoinColumn`、`@JoinColumns`:用于定义关联关系中的外键列。 - `@...

Global site tag (gtag.js) - Google Analytics