- 浏览: 144530 次
- 来自: ...
文章分类
最新评论
-
fisher:
真心感谢楼主! 解决了困扰我几天的大问题啊!
EntityManagerFactory -
悲剧了:
太棒了,我们项目正在用这个
struts2 convention-plugin -
nforce_com:
...
jpa继承关系详解 -
guanchuangsheng:
精辟~~
总算明白了·~
桥接模式和适配器模式的区别 -
lping2:
强,写得太全面了
EntityManagerFactory
7 Inheritance
对象使用引用以便关联到其它对象;关系型数据库表之间采用外键来描述表的关系。在关系型数据库中通常没有自然且有效的方法来描述类的继承关系。JPA通过Inheritance annotation提供了几种继承策略,它有以下属性:
InheritanceType strategy:用来声明继承策略。可选值是InheritanceType.SINGLE_TABLE、InheritanceType.JOINED和InheritanceType .TABLE_PER_CLASS。缺省值是InheritanceType.SINGLE_TABLE。
关于Inheritance的更多内容,可以参考Hibernate实战by Christian Bauer, Gavin King。
7.1 Single Table
InheritanceType.SINGLE_TABLE 策略为类的继承体系采用同一个表。表名是基类的名称。例如:
Java代码
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Base {
@Id
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Base {
@Id
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
使用MappingTool建立的表结构如下:
Sql代码
mysql> describe base;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| DTYPE | varchar(255) | YES | MUL | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe base;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| DTYPE | varchar(255) | YES | MUL | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
Java代码
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close();
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close(); 以上代码执行后,数据库中base表的数据如下(其中DTYPE列由OpenJPA自动插入,用于区分不同的class,关于Discriminator的详细用法请参考OpenJPA User's Guide):Sql代码
mysql> select * from base;
+----+-----------------+----------+--------------+--------------+
| id | baseName | DTYPE | derived1Name | derived2Name |
+----+-----------------+----------+--------------+--------------+
| 1 | base | Base | NULL | NULL |
| 2 | derived1's base | Derived1 | derived1 | NULL |
| 3 | derived2's base | Derived2 | NULL | derived2 |
+----+-----------------+----------+--------------+--------------+
mysql> select * from base;
+----+-----------------+----------+--------------+--------------+
| id | baseName | DTYPE | derived1Name | derived2Name |
+----+-----------------+----------+--------------+--------------+
| 1 | base | Base | NULL | NULL |
| 2 | derived1's base | Derived1 | derived1 | NULL |
| 3 | derived2's base | Derived2 | NULL | derived2 |
+----+-----------------+----------+--------------+--------------+
7.1.1 Advantages
InheritanceType.SINGLE_TABLE 策略的优势在于简单且性能高(因为不需要使用连接查询等)。如果类的继承体系中,子类和父类间的差异主要在于行为,同时子类之间以及子类和父类之间的属性差异不大(例如子类不增加属性或者增加的属性数目比较少),那么适用于这个策略。
7.1.2 Disadvantages
这个策略导致规范化级别降低。由于类继承体系中的每个类的属性都要映射到表的一列,因此当类的继承体系变的复杂的时候,表也随之变大。子类中属性对应的列必须声明为nullable。
7.2 Joined
InheritanceType.JOINED策略为类继承体系中的每个类创建不同的表。每个表只包含类中定义的列,因此在load一个子类的时候,JPA实现需要同时查询子类映射的表,以及通过关联查询所有的父类映射的表。PrimaryKeyJoinColumn annotation用来指定子类映射的表如何关联到父类映射的表。它有以下属性:
String name: 子类映射表中的列名。如果只有一个identity filed,那么缺省使用这个field对应的列名。
String referencedColumnName: 父类映射表中用来关联的列名。如果只有一个identity filed,那么缺省使用这个field对应的列名。
String columnDefinition: 数据库中列的数据类型。只有当JPA vendor支持通过metadata创建表的时候,这个属性才被使用。
以下是个简单的例子:
Java代码
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
使用MappingTool建立的表结构如下:
Sql代码
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
Java代码
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close();
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close(); 以上代码执行后,数据库中base表的数据如下:Sql代码
mysql> select * from base;
+----+-----------------+
| id | baseName |
+----+-----------------+
| 1 | derived2's base |
| 2 | derived1's base |
| 3 | base |
+----+-----------------+
mysql> select * from derived1;
+----+--------------+
| id | derived1Name |
+----+--------------+
| 2 | derived1 |
+----+--------------+
mysql> select * from derived2;
+----+--------------+
| id | derived2Name |
+----+--------------+
| 1 | derived2 |
+----+--------------+
mysql> select * from base;
+----+-----------------+
| id | baseName |
+----+-----------------+
| 1 | derived2's base |
| 2 | derived1's base |
| 3 | base |
+----+-----------------+
mysql> select * from derived1;
+----+--------------+
| id | derived1Name |
+----+--------------+
| 2 | derived1 |
+----+--------------+
mysql> select * from derived2;
+----+--------------+
| id | derived2Name |
+----+--------------+
| 1 | derived2 |
+----+--------------+
7.2.1 Advantages
InheritanceType. JOINED策略的优势在于数据库表中没有冗余字段,因此规范化级别比较高;当有新的子类加入到类的继承体系中时,已有表的schema无须修改。如果类的继承体系中,子类和父类间的差异不在于行为,同时子类间的属性差异比较大,那么适用于这个策略。
7.2.2 Disadvantages
由于在查询的时候需要进行关联,那么查询的速度会比其它方式慢。此外可能需要多个插入和更新语句来处理多个表。
7.3 Table Per Class
InheritanceType.TABLE_PER_CLASS策略为类继承体系中的每个类创建不同的表。和InheritanceType.JOINED策略不同的是,每个表中包含所有的子类和父类中定义的所有列。因此在load一个子类的时候,JPA实现只需要同时查询子类映射的表。
以下是个简单的例子:
Java代码
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
使用MappingTool建立的表结构如下:
Sql代码
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+ Java代码
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close();
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close(); 以上代码执行后,数据库中base表的数据如下:
Sql代码
mysql> select * from base;
+----+----------+
| id | baseName |
+----+----------+
| 1 | base |
+----+----------+
mysql> select * from derived1;
+----+-----------------+--------------+
| id | baseName | derived1Name |
+----+-----------------+--------------+
| 1 | derived1's base | derived1 |
+----+-----------------+--------------+
mysql> select * from derived2;
+----+-----------------+--------------+
| id | baseName | derived2Name |
+----+-----------------+--------------+
| 1 | derived2's base | derived2 |
+----+-----------------+--------------+
mysql> select * from base;
+----+----------+
| id | baseName |
+----+----------+
| 1 | base |
+----+----------+
mysql> select * from derived1;
+----+-----------------+--------------+
| id | baseName | derived1Name |
+----+-----------------+--------------+
| 1 | derived1's base | derived1 |
+----+-----------------+--------------+
mysql> select * from derived2;
+----+-----------------+--------------+
| id | baseName | derived2Name |
+----+-----------------+--------------+
| 1 | derived2's base | derived2 |
+----+-----------------+--------------+
7.3.1 Advantages
对于已知class类型的实例来说,这个策略十分有效。跟InheritanceType.JOINED策略类似,当有新的子类加入到类的继承体系中时,已有表的schema无须修改。
7.3.2 Disadvantages
这个策略在处理多态关系的时候会存在很多限制,此时某个引用(或者集合中的引用)可能指向任何子类的实例。由于无法使用关联查询,因此在查询的时候可能需要使用多个SQL语句或者使用UNION。
对象使用引用以便关联到其它对象;关系型数据库表之间采用外键来描述表的关系。在关系型数据库中通常没有自然且有效的方法来描述类的继承关系。JPA通过Inheritance annotation提供了几种继承策略,它有以下属性:
InheritanceType strategy:用来声明继承策略。可选值是InheritanceType.SINGLE_TABLE、InheritanceType.JOINED和InheritanceType .TABLE_PER_CLASS。缺省值是InheritanceType.SINGLE_TABLE。
关于Inheritance的更多内容,可以参考Hibernate实战by Christian Bauer, Gavin King。
7.1 Single Table
InheritanceType.SINGLE_TABLE 策略为类的继承体系采用同一个表。表名是基类的名称。例如:
Java代码
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Base {
@Id
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Base {
@Id
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
使用MappingTool建立的表结构如下:
Sql代码
mysql> describe base;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| DTYPE | varchar(255) | YES | MUL | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe base;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| DTYPE | varchar(255) | YES | MUL | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
Java代码
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close();
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close(); 以上代码执行后,数据库中base表的数据如下(其中DTYPE列由OpenJPA自动插入,用于区分不同的class,关于Discriminator的详细用法请参考OpenJPA User's Guide):Sql代码
mysql> select * from base;
+----+-----------------+----------+--------------+--------------+
| id | baseName | DTYPE | derived1Name | derived2Name |
+----+-----------------+----------+--------------+--------------+
| 1 | base | Base | NULL | NULL |
| 2 | derived1's base | Derived1 | derived1 | NULL |
| 3 | derived2's base | Derived2 | NULL | derived2 |
+----+-----------------+----------+--------------+--------------+
mysql> select * from base;
+----+-----------------+----------+--------------+--------------+
| id | baseName | DTYPE | derived1Name | derived2Name |
+----+-----------------+----------+--------------+--------------+
| 1 | base | Base | NULL | NULL |
| 2 | derived1's base | Derived1 | derived1 | NULL |
| 3 | derived2's base | Derived2 | NULL | derived2 |
+----+-----------------+----------+--------------+--------------+
7.1.1 Advantages
InheritanceType.SINGLE_TABLE 策略的优势在于简单且性能高(因为不需要使用连接查询等)。如果类的继承体系中,子类和父类间的差异主要在于行为,同时子类之间以及子类和父类之间的属性差异不大(例如子类不增加属性或者增加的属性数目比较少),那么适用于这个策略。
7.1.2 Disadvantages
这个策略导致规范化级别降低。由于类继承体系中的每个类的属性都要映射到表的一列,因此当类的继承体系变的复杂的时候,表也随之变大。子类中属性对应的列必须声明为nullable。
7.2 Joined
InheritanceType.JOINED策略为类继承体系中的每个类创建不同的表。每个表只包含类中定义的列,因此在load一个子类的时候,JPA实现需要同时查询子类映射的表,以及通过关联查询所有的父类映射的表。PrimaryKeyJoinColumn annotation用来指定子类映射的表如何关联到父类映射的表。它有以下属性:
String name: 子类映射表中的列名。如果只有一个identity filed,那么缺省使用这个field对应的列名。
String referencedColumnName: 父类映射表中用来关联的列名。如果只有一个identity filed,那么缺省使用这个field对应的列名。
String columnDefinition: 数据库中列的数据类型。只有当JPA vendor支持通过metadata创建表的时候,这个属性才被使用。
以下是个简单的例子:
Java代码
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
@PrimaryKeyJoinColumn(name="id", referencedColumnName="id")
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
使用MappingTool建立的表结构如下:
Sql代码
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+-------+
Java代码
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close();
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close(); 以上代码执行后,数据库中base表的数据如下:Sql代码
mysql> select * from base;
+----+-----------------+
| id | baseName |
+----+-----------------+
| 1 | derived2's base |
| 2 | derived1's base |
| 3 | base |
+----+-----------------+
mysql> select * from derived1;
+----+--------------+
| id | derived1Name |
+----+--------------+
| 2 | derived1 |
+----+--------------+
mysql> select * from derived2;
+----+--------------+
| id | derived2Name |
+----+--------------+
| 1 | derived2 |
+----+--------------+
mysql> select * from base;
+----+-----------------+
| id | baseName |
+----+-----------------+
| 1 | derived2's base |
| 2 | derived1's base |
| 3 | base |
+----+-----------------+
mysql> select * from derived1;
+----+--------------+
| id | derived1Name |
+----+--------------+
| 2 | derived1 |
+----+--------------+
mysql> select * from derived2;
+----+--------------+
| id | derived2Name |
+----+--------------+
| 1 | derived2 |
+----+--------------+
7.2.1 Advantages
InheritanceType. JOINED策略的优势在于数据库表中没有冗余字段,因此规范化级别比较高;当有新的子类加入到类的继承体系中时,已有表的schema无须修改。如果类的继承体系中,子类和父类间的差异不在于行为,同时子类间的属性差异比较大,那么适用于这个策略。
7.2.2 Disadvantages
由于在查询的时候需要进行关联,那么查询的速度会比其它方式慢。此外可能需要多个插入和更新语句来处理多个表。
7.3 Table Per Class
InheritanceType.TABLE_PER_CLASS策略为类继承体系中的每个类创建不同的表。和InheritanceType.JOINED策略不同的是,每个表中包含所有的子类和父类中定义的所有列。因此在load一个子类的时候,JPA实现只需要同时查询子类映射的表。
以下是个简单的例子:
Java代码
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Basic
private String baseName;
}
@Entity
public class Derived1 extends Base {
@Basic
private String derived1Name;
}
@Entity
public class Derived2 extends Base {
@Basic
private String derived2Name;
}
使用MappingTool建立的表结构如下:
Sql代码
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe base;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> describe derived1;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived1Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+
mysql> describe derived2;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| baseName | varchar(255) | YES | | NULL | |
| derived2Name | varchar(255) | YES | | NULL | |
+--------------+--------------+------+-----+---------+----------------+ Java代码
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close();
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
Base base = new Base();
base.setBaseName("base");
em.persist(base);
Derived1 d1 = new Derived1();
d1.setBaseName("derived1's base");
d1.setDerived1Name("derived1");
em.persist(d1);
Derived2 d2 = new Derived2();
d2.setBaseName("derived2's base");
d2.setDerived2Name("derived2");
em.persist(d2);
em.getTransaction().commit();
em.close(); 以上代码执行后,数据库中base表的数据如下:
Sql代码
mysql> select * from base;
+----+----------+
| id | baseName |
+----+----------+
| 1 | base |
+----+----------+
mysql> select * from derived1;
+----+-----------------+--------------+
| id | baseName | derived1Name |
+----+-----------------+--------------+
| 1 | derived1's base | derived1 |
+----+-----------------+--------------+
mysql> select * from derived2;
+----+-----------------+--------------+
| id | baseName | derived2Name |
+----+-----------------+--------------+
| 1 | derived2's base | derived2 |
+----+-----------------+--------------+
mysql> select * from base;
+----+----------+
| id | baseName |
+----+----------+
| 1 | base |
+----+----------+
mysql> select * from derived1;
+----+-----------------+--------------+
| id | baseName | derived1Name |
+----+-----------------+--------------+
| 1 | derived1's base | derived1 |
+----+-----------------+--------------+
mysql> select * from derived2;
+----+-----------------+--------------+
| id | baseName | derived2Name |
+----+-----------------+--------------+
| 1 | derived2's base | derived2 |
+----+-----------------+--------------+
7.3.1 Advantages
对于已知class类型的实例来说,这个策略十分有效。跟InheritanceType.JOINED策略类似,当有新的子类加入到类的继承体系中时,已有表的schema无须修改。
7.3.2 Disadvantages
这个策略在处理多态关系的时候会存在很多限制,此时某个引用(或者集合中的引用)可能指向任何子类的实例。由于无法使用关联查询,因此在查询的时候可能需要使用多个SQL语句或者使用UNION。
发表评论
-
EJB3 QL查询
2008-07-17 15:57 1490EJB3 QL查询 EJB3的查询语言是一种和SQL非常类似的 ... -
Table
2008-07-08 12:18 1972Table Table用来定义entity主表的name,ca ... -
Overview
2008-07-07 19:33 8851 Overview Apache OpenJPA是J ... -
Metadata
2008-07-07 19:32 13043 Metadata 通过javax.p ... -
EntityManagerFactory
2008-07-07 19:30 94824 EntityManagerFactory 4.1 Over ... -
Miscellaneous Features
2008-07-07 19:29 129310 Miscellaneous Features 10.1 ... -
Object Locking
2008-07-07 19:27 13138 Object Locking 8.1 Configurin ... -
Query
2008-07-07 19:26 15446 Query 6.1 JPQL Queries 6.1.1Q ... -
JNDI简介
2008-05-29 17:03 1673JNDI简介 & 简单示例 ... -
ejb2 和 ejb3的区别
2008-03-31 13:39 4209EJB 3 和EJB 2.1 的区别 从整个EJB 规范的 ...
相关推荐
jpa映射关系详解[参照].pdf
JPA JAPJPA JAPJPA JAPJPA JAPJPA JAPJPA JAPJPA JAPJPA JAPJPA JAPJPA JAP
Hibernate4之JPA规范配置详解
入门级别的jpa 详细解答,教程从简单到入门,容易上手
JPA注解 详解 1、@Entity(name="EntityName") 必须,name为可选,对应数据库中一的个表 2、@Table(name="",catalog="",schema="") 可选,通常和@Entity配合使用,只能标注在实体的class定义处,表示实体对应的数据库表...
JPA映射关系,多种映射关系的图解,适合EJB初学者,对JPA映射关系的了解.
java程序使用JPA注解详解 JPA注解详解 java 程序使用 JPA注解 详解
里面介绍了一些JPA的基础知识,适合想了解JPA的大虾门
JPA注解详解 默认情况下,JPA 持续性提供程序假设实体的所有持久字段均存储到一个名称为实体名称的数据库表中(请参阅 @Entity )。 在以下条件下,使用 @Table 批注指定与实体关联的主表:
JPA 详解,详细介绍了JPA的使用,从基本概念到具体例子
使用jpa映射关联和继承
JPA常用关系实现例子:一对一,一对多,多对一,多对多关系实现代码。
NULL 博文链接:https://zfei.iteye.com/blog/1453901
11_JPA详解_JPA中的一对多延迟加载与关系维护.zip 11_JPA详解_JPA中的一对多延迟加载与关系维护.zip
java程序使用JPA注解详解.doc
java程序使用JPA注解详解.zip java程序使用JPA注解详解.zip java程序使用JPA注解详解.zip java程序使用JPA注解详解.zip java程序使用JPA注解详解.zip
14_传智播客JPA详解_JPA中的多对多双向关联的各项关系操作.rar
11_传智播客JPA详解_JPA中的一对多延迟加载与关系维护.rar
jpa详解PPT
07_JPA详解_使用JPA加载_更新_删除对象.zip 07_JPA详解_使用JPA加载_更新_删除对象.zip