EJB3 - JPA - ORM
@Column(name = "LOB_XML", columnDefinition="clob")
@Lob
public byte[] getSecondaryTable() {
return secondaryTable;
}
@Entity
@Table(name="MY_USER")
@SecondaryTable(name="USER_PICTURES", pkJoinColumns=@PrimaryKeyJoinColumn(name="USER_ID"))
public class MyUser implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private BillingInfo billingInfo;
private byte[] picture;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="PICTURE", table="USER_PICTURES")
@Lob
@Basic(fetch=FetchType.LAZY)
public byte[] getPicture() {
return picture;
}
public void setPicture(byte[] picture) {
this.picture = picture;
}
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="USER_BILLING_ID", referencedColumnName="BILLING_ID")
public BillingInfo getBillingInfo() {
return billingInfo;
}
public void setBillingInfo(BillingInfo billingInfo) {
this.billingInfo = billingInfo;
}
}
create table USER_PICTURES (PICTURE blob, USER_ID number(19,0) not null, primary key (USER_BILLING_ID))
這段SQL錯誤的地方很明顯, 就在指定的PK不是USER_PICTURES的PK, 而是@OneToOne的FK. 去看source, 好像是在準備SQL statement的時候, 準備到SecondaryTable時, 跑去取org.hibernate.mapping.Constraint的columns, 應該存在的是SecondaryTable的PK, 取到的卻是OneToOne的column.
@Id
@Column(name="USER_ID")
@SequenceGenerator(
name="USER_SEQUENCE_GENERATOR", sequenceName="USER_SEQUENCE",
initialValue=1, allocationSize=1
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="USER_SEQUENCE_GENERATOR")
public Long getId() {
return id;
}
這樣就會建立一個sequence. create sequence USER_SEQUENCE
create sequence hibernate_sequence
@Id
@Column(name="USER_ID")
@TableGenerator(
name="USER_TABLE_GENERATOR", table="SEQUENCE_GENERATOR_TABLE",
pkColumnName="SEQUENCE_NAME", valueColumnName="SEQUENCE_VALUE",
pkColumnValue="USER_SEQUENCE", initialValue=1, allocationSize=100
)
@GeneratedValue(strategy = GenerationType.TABLE, generator="USER_TABLE_GENERATOR")
public Long getId() {
return id;
}
這樣就會建一個table來放PK value
create table SEQUENCE_GENERATOR_TABLE (
SEQUENCE_NAME varchar2(255), SEQUENCE_VALUE number(10,0)
)
再
insert into SEQUENCE_GENERATOR_TABLE (SEQUENCE_NAME, SEQUENCE_VALUE)
VALUES ('USER_SEQUENCE', 1)
@Embeddable
public class EmbeddedEntity implements Serializable, RegistedEntity {
private static final long serialVersionUID = 1L;
private Calendar embeddedTime;
@Column(name="EMBEDDED_TIME")
@Temporal(TemporalType.TIMESTAMP)
public Calendar getEmbeddedTime() {
return embeddedTime;
}
public void setEmbeddedTime(Calendar embeddedTime) {
this.embeddedTime = embeddedTime;
}
}
@Entity
@Table(name = "ONE")
public class OneTable implements Serializable {
...
@Embedded
public EmbeddedEntity getEmbeddedEntity() {
return embeddedEntity;
}
...
}
@Embedded
@AttributeOverrides(@AttributeOverride(
name = "embeddedTime",
column = @Column(name = "DIFF_EMBEDDED_TIME"))
)
public EmbeddedEntity getDifferentColumnEmbeddedEntity() {
return differentColumnEmbeddedEntity;
}
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="ANOTHER_ONE", referencedColumnName="ID")
public AnotherOneTable getAnotherOne() {
return anotherOne;
}
這樣在主entity會有個ANOTHER_ONE欄位, mapping到AnotherOneTable這個entity的ID欄位.
< relationship field/property name >_< name of referenced primary key column >
如以下範例
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn
public AnotherOneTable getAnotherOne() {
return anotherOne;
}
這樣就會在主table建立一個column: anotherOne_id mapping到AnotherOneTable這個entity的id欄位.
@Entity
@Table(name = "PARENT")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING, name="CHILD_TYPE", length=1)
public class Parent implements Serializable {
...
}
@Entity
@Table(name="GOOD_CHILD")
@DiscriminatorValue(value="G")
@PrimaryKeyJoinColumn(name="ID")
public class GoodChild extends Parent implements java.io.Serializable {
...
}
@Entity
@Table(name="USERS")
@SecondaryTable(name="USER_PICTURES", pkJoinColumns=@PrimaryKeyJoinColumn(name="USER_ID"))
public class MyUser implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private byte[] picture;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="PICTURE", table="USER_PICTURES")
@Lob
@Basic(fetch=FetchType.LAZY)
public byte[] getPicture() {
return picture;
}
public void setPicture(byte[] picture) {
this.picture = picture;
}
}
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Address address;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "EMPLOYEE_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToOne(cascade=CascadeType.ALL)
@PrimaryKeyJoinColumn // 如果PK和referencedColumn名稱一樣就不用指定名稱
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
@Table(name = "ADDRESS")
public class Address implements Serializable {
private static final long serialVersionUID = 1L;
private Long employeeId;
private String street;
@Id
@Column(name="EMPLOYEE_ID")
public Long getEmployeeId() {
return employeeId;
}
public void setEmployeeId(Long employeeId) {
this.employeeId = employeeId;
}
@Column(name="STREET")
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
這樣用hibernate自動建立的schema中address會少了FK constraint, 所以我又自己加了一個constraint
alter table address add constraint FK13246123456 foreign key (employee_id) references employee這段書上的說明不多, 不曉得我加了FK constraint之後是不是書上說的@PrimaryKeyJoinColumn使用模式
@Entity
public class Programmer implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private Set< Certification> certs = new HashSet();
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToMany(cascade=CascadeType.ALL, mappedBy="owner")
public Set< Certification> getCerts() {
return certs;
}
public void setCerts(Set< Certification> certs) {
this.certs = certs;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
public class Certification implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String certName;
private Programmer owner;
public void setId(Long id) {
this.id = id;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="CERT_NAME")
public String getCertName() {
return certName;
}
public void setCertName(String certName) {
this.certName = certName;
}
@ManyToOne
@JoinColumn(name="PROGRAMMER_ID")
public Programmer getOwner() {
return owner;
}
public void setOwner(Programmer owner) {
this.owner = owner;
}
}
@Entity
@Table(name="COMPONENT")
public class Component implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Component parent;
private List< Component> children = new ArrayList< Component>();
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name="COMPONENT_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@ManyToOne
@JoinColumn(name="PARENT_COMPONENT_ID", referencedColumnName="COMPONENT_ID")
public Component getParent() {
return parent;
}
public void setParent(Component parent) {
this.parent = parent;
}
@OneToMany(mappedBy="parent", cascade=CascadeType.ALL)
public List< Component> getChildren() {
return children;
}
public void setChildren(List< Component> children) {
this.children = children;
}
}
@Entity
@Table(name="SALES")
public class Sales implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private List< Product> products = new ArrayList< Product>();
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "SALES_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name = "NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 沒設定mappedBy就會是unidirectional
@ManyToMany(mappedBy="sales", cascade=CascadeType.ALL)
public List< Product> getProducts() {
return products;
}
public void setProducts(List< Product> products) {
this.products = products;
}
}
@Entity
@Table(name = "PRODUCT")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private List< Sales> sales = new ArrayList< Sales>();
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "PRODUCT_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name = "NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "PRODUCT_SALES", // PRODUCT_SALES是中間的table
// name是中間table的column, 若和現有column同名就不用referencedColumnName
joinColumns = @JoinColumn(name = "PRODUCT_ID"),
inverseJoinColumns = @JoinColumn(name = "SALES_ID")
)
public List< Sales> getSales() {
return sales;
}
public void setSales(List< Sales> sales) {
this.sales = sales;
}
}
public enum EmployeeType {
P, // Programmer
S // Sales
}
@Entity
@Table(name = "EMPLOYEE")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="EMPLOYEE_TYPE", length=1, discriminatorType=DiscriminatorType.STRING)
public abstract class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private EmployeeType employeeType;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "EMPLOYEE_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="EMPLOYEE_TYPE", insertable=false, updatable=false)
@Enumerated
public EmployeeType getEmployeeType() {
return employeeType;
}
public void setEmployeeType(EmployeeType employeeType) {
this.employeeType = employeeType;
}
}
@Entity
@DiscriminatorValue(value="P")
public class Programmer extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String lang;
@Column(name="LANG")
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
@Entity
@DiscriminatorValue(value="S")
public class Sales extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String product;
@Column(name="PRODUCT")
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
@Entity
@Table(name = "EMPLOYEE")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name="EMPLOYEE_TYPE", length=1, discriminatorType=DiscriminatorType.STRING)
public abstract class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private EmployeeType employeeType;
public void setId(Long id) {
this.id = id;
}
@Id
@Column(name = "EMPLOYEE_ID")
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
@Column(name="NAME")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="EMPLOYEE_TYPE")
@Enumerated(EnumType.STRING)
public EmployeeType getEmployeeType() {
return employeeType;
}
public void setEmployeeType(EmployeeType employeeType) {
this.employeeType = employeeType;
}
}
@Entity
@Table(name="PROGRAMMER")
@DiscriminatorValue(value="P")
@PrimaryKeyJoinColumn(name="EMPLOYEE_ID")
public class Programmer extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String lang;
@Column(name="LANG")
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
}
@Entity
@Table(name="SALES")
@DiscriminatorValue(value="S")
@PrimaryKeyJoinColumn(name="EMPLOYEE_ID")
public class Sales extends Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String product;
@Column(name="PRODUCT")
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
Posted at 01:25上午 六月 05, 2008 by shooeugenesea in EJB3 | 迴響[0]