- 浏览: 147445 次
- 来自: ...
文章分类
最新评论
-
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 1547EJB3 QL查询 EJB3的查询语言是一种和SQL非常类似的 ... -
Table
2008-07-08 12:18 2022Table Table用来定义entity主表的name,ca ... -
Overview
2008-07-07 19:33 9471 Overview Apache OpenJPA是J ... -
Metadata
2008-07-07 19:32 13443 Metadata 通过javax.p ... -
EntityManagerFactory
2008-07-07 19:30 95564 EntityManagerFactory 4.1 Over ... -
Miscellaneous Features
2008-07-07 19:29 134410 Miscellaneous Features 10.1 ... -
Object Locking
2008-07-07 19:27 13518 Object Locking 8.1 Configurin ... -
Query
2008-07-07 19:26 15956 Query 6.1 JPQL Queries 6.1.1Q ... -
JNDI简介
2008-05-29 17:03 1709JNDI简介 & 简单示例 ... -
ejb2 和 ejb3的区别
2008-03-31 13:39 4248EJB 3 和EJB 2.1 的区别 从整个EJB 规范的 ...
相关推荐
JPA注解详解 JPA(Java Persistence API)是Java企业版5(Java EE 5)的一部分,提供了一个对象关系映射方法,使得开发者可以使用声明方式定义如何将Java对象映射到关系数据库表。在JPA中,批注是一种使用元数据...
8. **Inheritance策略**:如果实体类继承自其他类,需考虑JPA的继承策略(如SINGLE_TABLE、JOINED、TABLE_PER_CLASS),这可能会影响到多对多关联的实现。 9. **事务管理**:由于多对多关联的修改可能涉及到多个...
8. **继承映射(Inheritance Mapping)**:JPA支持单表继承、联合继承和表格分层等策略,使你可以设计复杂的对象模型。 9. **懒加载(Lazy Loading)**:默认情况下,JPA实现如Hibernate支持懒加载,即关联的对象只...
JPA用于整合现有的ORM技术,可以简化现有Java EE和Java SE应用对象持久化的开发工作,实现ORM的统一。JPA详解视频教程 第19讲 映射关联和继承.avi
JPA详解通常是对JPA的深入解析,包括实体(Entity)、持久化上下文(Persistence Context)、托管状态(Managed State)、懒加载(Lazy Loading)、级联操作(Cascading)、关系映射(Relationship Mapping)、查询...
**JPA(Java Persistence API)**是Java平台上的一个标准,用于管理关系数据库中的数据,它简化了ORM(对象关系映射)的过程。本资料主要针对JPA的使用进行详细讲解,包括如何搭建JPA开发环境以及全局事务的介绍。 ...
了解以上基础后,你可以观看"03_传智播客JPA详解_搭建JPA开发环境和全局事务介绍"的自学视频,视频将更深入地展示如何操作和实践。学习过程中,你将看到如何配置JPA环境,创建并管理实体,以及如何在实际项目中运用...
6. **继承(Inheritance)**:JPA支持单表继承、联合继承和表-per-hierarchy等多种继承策略,这使得能够根据业务需求灵活设计实体结构。 7. **懒加载与急加载(Lazy vs. Eager Loading)**:默认情况下,关联是懒...
- **配置Repository**:Spring Data JPA提供了自动化的数据访问接口,只需要定义接口继承`JpaRepository`,即可进行基本的CRUD操作。 - **启动H2 Console(可选)**:SpringBoot默认集成了H2数据库,可以在开发...
8. `@Inheritance`: 用于处理继承关系,通过`InheritanceType.SINGLE_TABLE`(单表继承)、`InheritanceType.JOINED`(联合继承)和`InheritanceType.TABLE_PER_CLASS`(每类一张表)策略,控制子类在数据库中的存储...
- **继承(Inheritance)**:支持类继承关系的映射,如单表继承、联合继承、表格派生。 - **查询语言(JPQL)**:类似SQL的查询语言,用于在对象层进行查询。 - ** Criteria API**:提供动态构建查询的能力,比JPQL更...
**Java 持久化 API(JPA)详解(一)** Java 持久化 API(Java Persistence API),简称 JPA,是 Java 平台上的一个标准,用于管理关系数据库中的数据。JPA 提供了一种面向对象的方式来操作数据库,使得开发人员...
【Spring Data JPA 知识点详解】 Spring Data JPA 是 Spring Data 框架的一个重要组成部分,它为 Java 持久层提供了一种基于 JPA(Java Persistence API)的简单、高效的解决方案。JPA 是 Java 标准,用于管理关系...
**Spring-JPA 知识点详解** Spring-JPA,全称Spring Data JPA,是Spring框架的一个模块,它为Java Persistence API (JPA) 提供了面向切面的编程(AOP)支持,使得在Spring应用中使用JPA变得更加简单。JPA本身是Java...
3. **继承和多态性**:讲解如何处理实体类的继承关系,以及多态查询。 4. **转换和事件**:介绍实体状态转换和生命周期事件,如预加载、加载、保存、更新和删除事件。 5. **异步和并发**:讨论并发控制策略,如乐观...
**JPA一对多和多对一关系详解** Java Persistence API(JPA)是Java平台上的一个标准,用于处理对象关系映射(ORM),使得开发者可以使用面向对象的方式来操作数据库。在JPA中,实体间的关系映射是核心概念之一,...
**JPA(Java Persistence API)**是Java平台上的一个标准,用于管理关系数据库中的对象-关系映射(ORM)。它提供了方便的API和工具来处理持久化操作,使得开发人员可以更加专注于业务逻辑,而不是底层数据库操作。在...
《Spring Data JPA 实战详解》 Spring Data JPA 是 Spring 框架的一个重要模块,它为 Java Persistence API (JPA) 提供了统一的数据访问接口,简化了数据库操作。在 "spring-data-jpa-examples" 这个项目中,我们将...