One to many映射關係指的是兩個實體間一個實體能夠和多個實體有關聯關係,可是多的這一端只能和一的這一端的一個實例有關係。它是一個1 到 n的關係。例如在任何的公司員工能夠註冊多個銀行帳戶,一個銀行帳戶只能和一個員工相關聯,在這篇文章中咱們將會學習怎麼在Hibernate3中創建這種映射關係。java
問題陳述
咱們要寫兩個實體一個是Employee實體另外一個是Account實體,這樣多個銀行帳戶就能夠和一個員工關聯了,可是這些帳戶不能被兩個或以上的用戶共享。
設計解決方案
這種問題能夠使用兩種方式解決。一種方式是在Account表中設置一個外鍵EMPLOYEE_ID,這一列指向Employee表的主鍵,這種方式沒有兩個帳號能夠和多個用戶相關聯,顯然,爲了完成這種限制,帳號應該是獨特的。另外一種方式是創建一個鏈接表,好比說是叫EMPLOYEE_ACCOUNT,這個表有兩列,EMP_ID做爲EMPLOYEE表中主鍵的外鍵,對於ACCOUNT_ID也是這種狀況。
使用外鍵鏈接
這種方式,兩個實體都要負責創建關係並維護這種關係,EMPLOYEE實體應該申明的關係是one to many,Account實體應該聲明的關係是many to one。首先來看一下關係設計:
EMPLOYEE實體
- package hibernate.test.oneToMany.foreignKeyAsso;
-
- import java.io.Serializable;
- import java.util.Set;
-
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.OneToMany;
- import javax.persistence.Table;
- import javax.persistence.UniqueConstraint;
-
- @Entity(name = "ForeignKeyAssoEntity")
- @Table(name = "Employee", uniqueConstraints = {
- @UniqueConstraint(columnNames = "ID"),
- @UniqueConstraint(columnNames = "EMAIL") })
- public class EmployeeEntity implements Serializable {
-
- private static final long serialVersionUID = -1798070786993154676L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "ID", unique = true, nullable = false)
- private Integer employeeId;
-
- @Column(name = "EMAIL", unique = true, nullable = false, length = 100)
- private String email;
-
- @Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
- private String firstName;
-
- @Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
- private String lastName;
-
- @OneToMany(cascade=CascadeType.ALL)
- @JoinColumn(name="EMPLOYEE_ID")
- private Set<AccountEntity> accounts;
-
- public Integer getEmployeeId() {
- return employeeId;
- }
-
- public void setEmployeeId(Integer employeeId) {
- this.employeeId = employeeId;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public String getFirstName() {
- return firstName;
- }
-
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
-
- public String getLastName() {
- return lastName;
- }
-
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
-
- public Set<AccountEntity> getAccounts() {
- return accounts;
- }
-
- public void setAccounts(Set<AccountEntity> accounts) {
- this.accounts = accounts;
- }
- }
Account實體
- package hibernate.test.oneToMany.foreignKeyAsso;
-
- import java.io.Serializable;
-
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.ManyToOne;
- import javax.persistence.Table;
- import javax.persistence.UniqueConstraint;
-
- @Entity(name = "ForeignKeyAssoAccountEntity")
- @Table(name = "ACCOUNT", uniqueConstraints = {
- @UniqueConstraint(columnNames = "ID")})
- public class AccountEntity implements Serializable
- {
-
- private static final long serialVersionUID = -6790693372846798580L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "ID", unique = true, nullable = false)
- private Integer accountId;
-
- @Column(name = "ACC_NUMBER", unique = true, nullable = false, length = 100)
- private String accountNumber;
-
- @ManyToOne
- private EmployeeEntity employee;
-
- public Integer getAccountId() {
- return accountId;
- }
-
- public void setAccountId(Integer accountId) {
- this.accountId = accountId;
- }
-
- public String getAccountNumber() {
- return accountNumber;
- }
-
- public void setAccountNumber(String accountNumber) {
- this.accountNumber = accountNumber;
- }
-
- public EmployeeEntity getEmployee() {
- return employee;
- }
-
- public void setEmployee(EmployeeEntity employee) {
- this.employee = employee;
- }
- }
測試代碼
- package hibernate.test.oneToMany;
-
- import hibernate.test.HibernateUtil;
- import hibernate.test.oneToMany.foreignKeyAsso.AccountEntity;
- import hibernate.test.oneToMany.foreignKeyAsso.EmployeeEntity;
-
- import java.util.HashSet;
- import java.util.Set;
-
- import org.hibernate.Session;
-
- public class TestForeignKeyAssociation
- {
-
- public static void main(String[] args)
- {
- Session session = HibernateUtil.getSessionFactory().openSession();
- session.beginTransaction();
-
- AccountEntity account1 = new AccountEntity();
- account1.setAccountNumber("Account detail 1");
-
- AccountEntity account2 = new AccountEntity();
- account2.setAccountNumber("Account detail 2");
-
- AccountEntity account3 = new AccountEntity();
- account3.setAccountNumber("Account detail 3");
-
-
- EmployeeEntity firstEmployee = new EmployeeEntity();
- firstEmployee.setEmail("demo-user-first@mail.com");
- firstEmployee.setFirstName("demo-one");
- firstEmployee.setLastName("user-one");
-
- EmployeeEntity secondEmployee = new EmployeeEntity();
- secondEmployee.setEmail("demo-user-second@mail.com");
- secondEmployee.setFirstName("demo-two");
- secondEmployee.setLastName("user-two");
-
- Set<AccountEntity> accountsOfFirstEmployee = new HashSet<AccountEntity>();
- accountsOfFirstEmployee.add(account1);
- accountsOfFirstEmployee.add(account2);
-
- Set<AccountEntity> accountsOfSecondEmployee = new HashSet<AccountEntity>();
- accountsOfSecondEmployee.add(account3);
-
- firstEmployee.setAccounts(accountsOfFirstEmployee);
- secondEmployee.setAccounts(accountsOfSecondEmployee);
-
- session.save(firstEmployee);
- session.save(secondEmployee);
-
- session.getTransaction().commit();
- HibernateUtil.shutdown();
- }
- }
- Output:
-
- Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
- Hibernate: insert into ACCOUNT (ACC_NUMBER, employee_ID) values (?, ?)
- Hibernate: insert into ACCOUNT (ACC_NUMBER, employee_ID) values (?, ?)
- Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
- Hibernate: insert into ACCOUNT (ACC_NUMBER, employee_ID) values (?, ?)
- Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
- Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
- Hibernate: update ACCOUNT set EMPLOYEE_ID=? where ID=?
使用關聯表
這種方式使用關聯表存儲兩個實體間的關係@JoinTable註解是用來創建這種關係的,先來看一下數據庫模式
EMPLOYEE實體
- package hibernate.test.oneToMany.joinTable;
-
- import java.io.Serializable;
- import java.util.Set;
-
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.JoinTable;
- import javax.persistence.OneToMany;
- import javax.persistence.Table;
- import javax.persistence.UniqueConstraint;
-
- @Entity(name = "JoinTableEmployeeEntity")
- @Table(name = "Employee", uniqueConstraints = {
- @UniqueConstraint(columnNames = "ID"),
- @UniqueConstraint(columnNames = "EMAIL") })
- public class EmployeeEntity implements Serializable
- {
- private static final long serialVersionUID = -1798070786993154676L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "ID", unique = true, nullable = false)
- private Integer employeeId;
-
- @Column(name = "EMAIL", unique = true, nullable = false, length = 100)
- private String email;
-
- @Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
- private String firstName;
-
- @Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
- private String lastName;
-
- @OneToMany(cascade=CascadeType.ALL)
- @JoinTable(name="EMPLOYEE_ACCOUNT", joinColumns={@JoinColumn(name="EMPLOYEE_ID", referencedColumnName="ID")}
- , inverseJoinColumns={@JoinColumn(name="ACCOUNT_ID", referencedColumnName="ID")})
- private Set<AccountEntity> accounts;
-
- public Integer getEmployeeId() {
- return employeeId;
- }
-
- public void setEmployeeId(Integer employeeId) {
- this.employeeId = employeeId;
- }
-
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public String getFirstName() {
- return firstName;
- }
-
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
-
- public String getLastName() {
- return lastName;
- }
-
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
-
- public Set<AccountEntity> getAccounts() {
- return accounts;
- }
-
- public void setAccounts(Set<AccountEntity> accounts) {
- this.accounts = accounts;
- }
- }
Account實體
- package hibernate.test.oneToMany.joinTable;
-
- import java.io.Serializable;
-
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.Table;
- import javax.persistence.UniqueConstraint;
-
- @Entity(name = "JoinTableAccountEntity")
- @Table(name = "ACCOUNT", uniqueConstraints = {
- @UniqueConstraint(columnNames = "ID")})
- public class AccountEntity implements Serializable
- {
-
- private static final long serialVersionUID = -6790693372846798580L;
-
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "ID", unique = true, nullable = false)
- private Integer accountId;
-
- @Column(name = "ACC_NUMBER", unique = true, nullable = false, length = 100)
- private String accountNumber;
-
- public Integer getAccountId() {
- return accountId;
- }
-
- public void setAccountId(Integer accountId) {
- this.accountId = accountId;
- }
-
- public String getAccountNumber() {
- return accountNumber;
- }
-
- public void setAccountNumber(String accountNumber) {
- this.accountNumber = accountNumber;
- }
- }
在配置文件中配置實體,咱們已經有了兩個在運行時的實體,咱們必須在配置文件中增長他們。請注意只有一個集合實體能夠在配置文件中配置,不然會有意外的狀況發生
- < ?xml version="1.0" encoding="utf-8"?>
- < !DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
- <property name="hibernate.connection.url">jdbc:mysql:
- <property name="hibernate.connection.password">XXXXXX</property>
- <property name="hibernate.connection.username">root</property>
- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
- <property name="show_sql">true</property>
- <property name="hbm2ddl.auto">create</property>
- <mapping clas="hibernate.test.oneToMany.foreignKeyAsso.AccountEntity"></mapping>
- <mapping clas="hibernate.test.oneToMany.foreignKeyAsso.EmployeeEntity"></mapping>
- </session-factory>
- </hibernate-configuration>
測試代碼:
- package hibernate.test.oneToMany;
-
- import hibernate.test.HibernateUtil;
- import hibernate.test.oneToMany.joinTable.AccountEntity;
- import hibernate.test.oneToMany.joinTable.EmployeeEntity;
-
- import java.util.HashSet;
- import java.util.Set;
-
- import org.hibernate.Session;
-
- public class TestJoinTable
- {
- public static void main(String[] args)
- {
- Session session = HibernateUtil.getSessionFactory().openSession();
- session.beginTransaction();
-
- AccountEntity account1 = new AccountEntity();
- account1.setAccountNumber("123-345-65454");
-
- AccountEntity account2 = new AccountEntity();
- account2.setAccountNumber("123-345-6542222");
-
-
- EmployeeEntity emp = new EmployeeEntity();
- emp.setEmail("demo-user@mail.com");
- emp.setFirstName("demo");
- emp.setLastName("user");
-
- Set<AccountEntity> accounts = new HashSet<AccountEntity>();
- accounts.add(account1);
- accounts.add(account2);
-
- emp.setAccounts(accounts);
-
- session.save(emp);
-
- session.getTransaction().commit();
- HibernateUtil.shutdown();
- }
- }
-
- Output:
-
- Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?)
- Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
- Hibernate: insert into ACCOUNT (ACC_NUMBER) values (?)
- Hibernate: insert into EMPLOYEE_ACCOUNT (EMPLOYEE_ID, ACCOUNT_ID) values (?, ?)
- Hibernate: insert into EMPLOYEE_ACCOUNT (EMPLOYEE_ID, ACCOUNT_ID) values (?, ?)