JPA比较罕见的应用
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name= "file_type")
@Table(name="t_file")
public abstract class FileParent implements Serializable{
@Id
@TableGenerator(name="t_file_seq",allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE, generator="t_file_seq")
private String id;
//getters/setters;
}
@Embeddable
public class FileHeader{
@Column(name="header_attr1")
protected String headerAttr1;
@Column(name="header_attr2")
protected String headerAttr2;
// getters/setters...
}
@Embedabble
public class FileBody{
}
@Entity
@DiscriminatorValue(value="0")
public class TypeAFile extends FileParent implements Serializable{
@Embedded
private TypeAFileHeader fileHeader;
@Embedded
private TypeAFileBody fileBody;
public FileHeader getFileHeader(){
return this.fileHeader
}
public void setFileHeader(FileHeader fileHeader){
this.fileHeader = (TypeAFileHeader)fileHeader;
} public FileBody getFileBody(){
return this.fileBody;
}
public void setFileBody(FileBody fileBody){
this.fileBody = (TypeAFileBody)fileBody;
}
}@Embeddable
public class TypeAFileHeader extends FileHeader{
@Column(name="header_attr1")
public String getHeaderAttr1(){
return this.headerAttr1;
}
public void setHeaderAttr1(String headerAttr1){
this.headerAttr1 = headerAttr1;
} @Column(name="header_attr2")
public String getHeaderAttr2(){
return this.headerAttr2;
}
public void setHeaderAttr2(String headerAttr2){
this.headerAttr2 = headerAttr2;
}
}
@Embedabble
public class TypeAFileBody{
@Column(name="type_a_body_attr1")
private String typeAbodyAttr1;
@Column(name="type_a_body_attr2")
private String typeAbodyAttr2;
// getters/setters...
}@Entity
@DiscriminatorValue(value="1")
public class TypeBFile extends FileParent implements Serializable{
@Embedded
private TypeBFileHeader fileHeader;
@Embedded
private TypeBFileBody fileBody;
public FileHeader getFileHeader(){
return this.fileHeader
}
public void setFileHeader(FileHeader fileHeader){
this.fileHeader = (TypeBFileHeader)fileHeader;
} public FileBody getFileBody(){
return this.fileBody;
}
public void setFileBody(FileBody fileBody){
this.fileBody = (TypeBFileBody)fileBody;
}
}@Embeddable
public class TypeBFileHeader extends FileHeader{
@Column(name="header_attr1")
public String getHeaderAttr1(){
return this.headerAttr1;
}
public void setHeaderAttr1(String headerAttr1){
this.headerAttr1 = headerAttr1;
} @Column(name="header_attr2")
public String getHeaderAttr2(){
return this.headerAttr2;
}
public void setHeaderAttr2(String headerAttr2){
this.headerAttr2 = headerAttr2;
}
}
@Embedabble
public class TypeBFileBody{
@Column(name="type_a_body_attr1")
private String typeBbodyAttr1;
@Column(name="type_b_body_attr2")
private String typeBbodyAttr2;
@Column(name="type_b_body_attr3")
private String typeBbodyAttr3;
// getters/setters...
}请问以上的JPA代码为什么不能生成以下的表结构:
t_file(id,dtype,header_attr1,header_attr2,type_a_body_attr1,type_a_body_attr2,type_b_body_attr1,type_b_body_attr2,type_b_body_attr3)
??
在这个里面,综合了@Inheritance与@Embedded批注的应用,
照理说应该可以生成以上的表结构的,但是在运行总是不行。
麻烦大虾指点下,谢谢。
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name= "file_type")
@Table(name="t_file")
public abstract class FileParent implements Serializable{
@Id
@TableGenerator(name="t_file_seq",allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE, generator="t_file_seq")
private String id;
//getters/setters;
}
@Embeddable
public class FileHeader{
@Column(name="header_attr1")
protected String headerAttr1;
@Column(name="header_attr2")
protected String headerAttr2;
// getters/setters...
}
@Embedabble
public class FileBody{
}
@Entity
@DiscriminatorValue(value="0")
public class TypeAFile extends FileParent implements Serializable{
@Embedded
private TypeAFileHeader fileHeader;
@Embedded
private TypeAFileBody fileBody;
public FileHeader getFileHeader(){
return this.fileHeader
}
public void setFileHeader(FileHeader fileHeader){
this.fileHeader = (TypeAFileHeader)fileHeader;
} public FileBody getFileBody(){
return this.fileBody;
}
public void setFileBody(FileBody fileBody){
this.fileBody = (TypeAFileBody)fileBody;
}
}@Embeddable
public class TypeAFileHeader extends FileHeader{
@Column(name="header_attr1")
public String getHeaderAttr1(){
return this.headerAttr1;
}
public void setHeaderAttr1(String headerAttr1){
this.headerAttr1 = headerAttr1;
} @Column(name="header_attr2")
public String getHeaderAttr2(){
return this.headerAttr2;
}
public void setHeaderAttr2(String headerAttr2){
this.headerAttr2 = headerAttr2;
}
}
@Embedabble
public class TypeAFileBody{
@Column(name="type_a_body_attr1")
private String typeAbodyAttr1;
@Column(name="type_a_body_attr2")
private String typeAbodyAttr2;
// getters/setters...
}@Entity
@DiscriminatorValue(value="1")
public class TypeBFile extends FileParent implements Serializable{
@Embedded
private TypeBFileHeader fileHeader;
@Embedded
private TypeBFileBody fileBody;
public FileHeader getFileHeader(){
return this.fileHeader
}
public void setFileHeader(FileHeader fileHeader){
this.fileHeader = (TypeBFileHeader)fileHeader;
} public FileBody getFileBody(){
return this.fileBody;
}
public void setFileBody(FileBody fileBody){
this.fileBody = (TypeBFileBody)fileBody;
}
}@Embeddable
public class TypeBFileHeader extends FileHeader{
@Column(name="header_attr1")
public String getHeaderAttr1(){
return this.headerAttr1;
}
public void setHeaderAttr1(String headerAttr1){
this.headerAttr1 = headerAttr1;
} @Column(name="header_attr2")
public String getHeaderAttr2(){
return this.headerAttr2;
}
public void setHeaderAttr2(String headerAttr2){
this.headerAttr2 = headerAttr2;
}
}
@Embedabble
public class TypeBFileBody{
@Column(name="type_a_body_attr1")
private String typeBbodyAttr1;
@Column(name="type_b_body_attr2")
private String typeBbodyAttr2;
@Column(name="type_b_body_attr3")
private String typeBbodyAttr3;
// getters/setters...
}请问以上的JPA代码为什么不能生成以下的表结构:
t_file(id,dtype,header_attr1,header_attr2,type_a_body_attr1,type_a_body_attr2,type_b_body_attr1,type_b_body_attr2,type_b_body_attr3)
??
在这个里面,综合了@Inheritance与@Embedded批注的应用,
照理说应该可以生成以上的表结构的,但是在运行总是不行。
麻烦大虾指点下,谢谢。
2 然后再逐步修改代码,变成你期望的模样总之,不要一下子变动的因素太多,让你根本找不到头绪。一点一点refactor的过程
楼主:你说得很对,直接使用Entity的集成,上一级的是拿不到的。
在子类中再get一下父类中的属性
再加上@Column批注,就可以了,如下:
@Embeddable
public class TypeAFileHeader extends FileHeader{
@Column(name="header_attr1")
public String getHeaderAttr1(){
return this.headerAttr1;
}
public void setHeaderAttr1(String headerAttr1){
this.headerAttr1 = headerAttr1;
} @Column(name="header_attr2")
public String getHeaderAttr2(){
return this.headerAttr2;
}
public void setHeaderAttr2(String headerAttr2){
this.headerAttr2 = headerAttr2;
}
} 谢谢你的建议,经过一上午的调试,这个表结构能够生成了。
但是现在有另外一个问题:@Embeddable的实体中能不能有一个
@OneToMany属性?如
在
@Embedabble
public class TypeBFileBody{
@Column(name="type_a_body_attr1")
private String typeBbodyAttr1;
@Column(name="type_b_body_attr2")
private String typeBbodyAttr2;
@Column(name="type_b_body_attr3")
private String typeBbodyAttr3; @OneToMany(mappedBy="typeBFileBody")
private List<AppendixFile> list;
// getters/setters...
}
@Entity
public class AppendixFile{
@Id
private String id;
@JoinColumn(name="type_b_file_body_id",referencedColumnName="...")
@ManyToOne
private TypeBFileBody typeBFileBody;
// getters/setter...
}这样能行吗???
谢谢,帮帮忙。
为方法大家借鉴,现将解决方法给出如下:
把TypeBFileBody类中的
@OneToMany(mappedBy="typeBFileBody")
private List <AppendixFile> list; 放到
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name= "file_type")
@Table(name="t_file")
public abstract class FileParent implements Serializable{
@Id
@TableGenerator(name="t_file_seq",allocationSize=1)
@GeneratedValue(strategy=GenerationType.TABLE, generator="t_file_seq")
private String id;
//getters/setters;
}
中,并把类AppendixFile改成如下就行:
@Entity
public class AppendixFile{
@Id
private String id;
@JoinColumn(name="type_b_file_body_id")
//注意一定不能是@JoinColumn(name="type_b_file_body_id",referencedColumnName="id")
// 否则会报类FileParent.id没有映射的异常
@ManyToOne
private TypeBFileBody typeBFileBody;
// getters/setter...
}
embeddable类中不适合加@OneToMany的映射,因为它没有@Id
(目前我是这么理解的,不知道是不是)
应该是:把AppendixFile外键关联到TypeBFile.
解决方法如下:
把TypeBFileBody类中的
@OneToMany(mappedBy="typeBFileBody")
private List <AppendixFile> list;
修改一下
放到 TypeBFile 中,如下
@Entity
@DiscriminatorValue(value="1")
public class TypeBFile extends FileParent implements Serializable{
@Embedded
private TypeBFileHeader fileHeader;
@Embedded
private TypeBFileBody fileBody;
@OneToMany(mappedBy="typeBFile")
private List <AppendixFile> list;
public FileHeader getFileHeader(){
return this.fileHeader
} public void setFileHeader(FileHeader fileHeader){
this.fileHeader = (TypeBFileHeader)fileHeader;
} public FileBody getFileBody(){
return this.fileBody;
} public void setFileBody(FileBody fileBody){
this.fileBody = (TypeBFileBody)fileBody;
}
}
,并把类AppendixFile改成如下就行:
@Entity
public class AppendixFile{
@Id
private String id;
@JoinColumn(name="type_b_file_body_id")
//注意一定不能是@JoinColumn(name="type_b_file_body_id",referencedColumnName="id")
// 否则会报类FileParent.id没有映射的异常
@ManyToOne
private TypeBFile typeBFile ;
// getters/setter...
}
@Embedded
FileHeader header; // getter/setter
}@Embeddable
abstract class FileHeader{ // @Embeddable 能是Abstract吗?
}@Embeddable
class MyFileHeader{
//...
}main(..){ MyFile myFile = new MyFile();
myFile.setHeader(new MyFileHeader()); //以此实现多态,JPA支持吗?
}以上方式能行吗?
@Embeddable
abstract class FileHeader{ // @Embeddable 能是Abstract吗?
} 这种方式都无法 通过编译
javax.persistence.PersistenceException: org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: testjpa.FileHeader
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:637)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:226)
at testjpa.Main.persist(Main.java:55)
at testjpa.Main.main(Main.java:36)
Caused by: org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: testjpa.FileHeader
楼上的,
@Embeddable 是支持继承,多态的。
//Embeddable类是BaseInfo,其中UserBaseInfo继承自BaseInfo
@Entity
@Table(name = "Users")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name= "BBB",discriminatorType=DiscriminatorType.INTEGER)
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "customer_gen")
@TableGenerator(name = "customer_gen",
table = "tb_generator",
pkColumnName = "gen_name",
valueColumnName = "gen_value",
pkColumnValue = "id",allocationSize = 1)
private Long id;
private String name;
@Embedded
private BaseInfo baseInfo;
get/set......
}@Embeddable
public class BaseInfo implements java.io.Serializable {
private String baseName;
get/set......
}
//UserBaseInfo类继承BaseInfo类
@Embeddable
public class UserBaseInfo extends BaseInfo implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private String address;
private String email;
private String telephone;
get/set......
}
//Man类继承User类
@Entity
@DiscriminatorValue(value="2")
public class Man extends User implements Serializable {
private String manName;
get/set......
}
//Woman类继承User类
@Entity
@DiscriminatorValue(value="1")
public class Woman extends User implements Serializable {
private String womainName;
get/set......
}
//测试类如下
public class Main extends User {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Main m = new Main();
UserBaseInfo userBaseInfo = new UserBaseInfo();
userBaseInfo.setBaseName("haha112");
userBaseInfo.setAddress("黑龙江");
userBaseInfo.setEmail("[email protected]");
Man man = new Man();
man.setManName("男人aaaa");
man.setBaseInfo(userBaseInfo);
m.persist(man);
} public void persist(Object object) {
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("TestjpaPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
try {
em.persist(object);
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
em.getTransaction().rollback();
} finally {
em.close();
}
}
}
persistence.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="TestjpaPU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>testjpa.User</class>
<class>testjpa.Man</class>
<class>testjpa.Woman</class>
<class>testjpa.MutiKeyTable</class>
<class>testjpa.SinglePrimary</class>
<properties>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.driver_class" value="net.sourceforge.jtds.jdbc.Driver"/>
<property name="hibernate.connection.password" value="123456"/>
<property name="hibernate.connection.url" value="jdbc:jtds:sqlserver://localhost:1433/testjpa"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>数据库字段如下
BBB id baseName name manName womanName
2 1 haha112 NULL 男人aaaa NULL可以说明继承类的字段没有被影射到数据库如果你在User类里面把BaseInfo 换成 UserBaseInfo的话,数据库字段如下BBB id address email telephone name manName womanName
2 1 哈尔滨333333333 [email protected] NULL NULL 男人aaaa NULL
可以看出BaseInfo中的baseName没有被映射到数据库代码不全,可能有不对的地方,请指正