Hibernate-one-to-one-mapping
Hibernate-1対1マッピング
*1対1* の関連付けは、*多対1 *の関連付けに似ていますが、列が一意に設定されるという違いがあります。 たとえば、住所オブジェクトを単一の従業員オブジェクトに関連付けることができます。
RDBMSテーブルを定義する
次の構造を持つ従業員レコードをEMPLOYEEテーブルに保存する必要がある状況を考えます-
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
address INT NOT NULL,
PRIMARY KEY (id)
);
さらに、住所は1人の従業員にのみ関連付けることができるため、この関連付けは1対1の関連付けを使用して提示できます。 アドレス関連の情報は、次の構造を持つ別のテーブルに保存します-
create table ADDRESS (
id INT NOT NULL auto_increment,
street_name VARCHAR(40) default NULL,
city_name VARCHAR(40) default NULL,
state_name VARCHAR(40) default NULL,
zipcode VARCHAR(10) default NULL,
PRIMARY KEY (id)
);
両方のRBDMSテーブルを作成し、次の実装に備えて準備しておきます。
POJOクラスを定義する
EMPLOYEEテーブルに関連し、Address型の変数を持つオブジェクトを永続化するために使用されるPOJOクラス Employee を実装しましょう。
import java.util.*;
public class Employee{
private int id;
private String firstName;
private String lastName;
private int salary;
private Address address;
public Employee() {}
public Employee(String fname, String lname, int salary, Address address ) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
this.address = address;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
public Address getAddress() {
return address;
}
public void setAddress( Address address ) {
this.address = address;
}
}
アドレスオブジェクトをADDRESSテーブルに格納および取得できるように、ADDRESSテーブルに対応する別のPOJOクラスを定義する必要があります。
import java.util.*;
public class Address{
private int id;
private String street;
private String city;
private String state;
private String zipcode;
public Address() {}
public Address(String street, String city, String state, String zipcode) {
this.street = street;
this.city = city;
this.state = state;
this.zipcode = zipcode;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet( String street ) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity( String city ) {
this.city = city;
}
public String getState() {
return state;
}
public void setState( String state ) {
this.state = state;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode( String zipcode ) {
this.zipcode = zipcode;
}
}
Hibernateマッピングファイルの定義
定義済みのクラスをデータベーステーブルにマップする方法をHibernateに指示するマッピングファイルを開発しましょう。 <many-to-one>要素は、EMPLOYEEエンティティとADDRESSエンティティ間の1対1の関係を確立するルールを定義するために使用されますが、列属性は unique 制約に設定され、マッピングファイルの残りは残ります多対1の関連付けの場合のように。
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
<many-to-one name = "address" column = "address" unique="true"
class="Address" not-null="true"/>
</class>
<class name = "Address" table="ADDRESS">
<meta attribute = "class-description">
This class contains the address detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "street" column = "street_name" type = "string"/>
<property name = "city" column = "city_name" type = "string"/>
<property name = "state" column = "state_name" type = "string"/>
<property name = "zipcode" column = "zipcode" type = "string"/>
</class>
</hibernate-mapping>
マッピングドキュメントは、<classname> .hbm.xml形式のファイルに保存する必要があります。 マッピング文書をファイルEmployee.hbm.xmlに保存しました。 あなたはすでにマッピングの詳細のほとんどに精通していますが、マッピングファイルのすべての要素をもう一度見てみましょう-
- マッピングドキュメントは、各クラスに対応する2つの<class>要素を含むルート要素として <hibernate-mapping> を持つXMLドキュメントです。
- <class> 要素は、Javaクラスからデータベーステーブルへの特定のマッピングを定義するために使用されます。 Javaクラス名はクラス要素の name 属性を使用して指定され、データベーステーブル名は table 属性を使用して指定されます。
- <meta> 要素はオプションの要素であり、クラスの説明を作成するために使用できます。
- <id> 要素は、クラスの一意のID属性をデータベーステーブルの主キーにマップします。 id要素の name 属性はクラスのプロパティを参照し、 column 属性はデータベーステーブルの列を参照します。 type 属性はhibernateマッピングタイプを保持します。このマッピングタイプはJavaからSQLデータタイプに変換します。
- id要素内の <generator> 要素は、主キー値を自動的に生成するために使用されます。 ジェネレーター要素の class 属性は native に設定され、休止状態が基になるデータベースの機能に応じて主キーを作成するために identity、sequence または hilo アルゴリズムを選択できるようにします。
- <property> 要素は、Javaクラスプロパティをデータベーステーブルの列にマップするために使用されます。 要素の name 属性はクラスのプロパティを参照し、 column 属性はデータベーステーブルの列を参照します。 type 属性はhibernateマッピングタイプを保持します。このマッピングタイプはJavaからSQLデータタイプに変換します。
- <many-to-one> 要素は、EMPLOYEEエンティティとADDRESSエンティティ間の関係を設定するために使用されます。 name 属性は、親クラスの定義済み変数に設定されます。この例では、_address_です。 column 属性を使用して、親テーブルEMPLOYEEの列名を設定します。これは unique に設定されているため、1つのEmployeeオブジェクトのみが住所オブジェクトに関連付けることができます。
最後に、main()メソッドを使用してアプリケーションクラスを作成し、アプリケーションを実行します。 このアプリケーションを使用して、少数の従業員のレコードと証明書を保存し、それらのレコードにCRUD操作を適用します。
import java.util.*;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/*Let us have one address object*/
Address address1 = ME.addAddress("Kondapur","Hyderabad","AP","532");
/*Add employee records in the database*/
Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, address1);
/*Let us have another address object*/
Address address2 = ME.addAddress("Saharanpur","Ambehta","UP","111");
/*Add another employee record in the database*/
Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, address2);
/*List down all the employees*/
ME.listEmployees();
/*Update employee's salary records*/
ME.updateEmployee(empID1, 5000);
/*List down all the employees*/
ME.listEmployees();
}
/*Method to add an address record in the database*/
public Address addAddress(String street, String city, String state, String zipcode) {
Session session = factory.openSession();
Transaction tx = null;
Integer addressID = null;
Address address = null;
try {
tx = session.beginTransaction();
address = new Address(street, city, state, zipcode);
addressID = (Integer) session.save(address);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return address;
}
/*Method to add an employee record in the database*/
public Integer addEmployee(String fname, String lname, int salary, Address address){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary, address);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/*Method to list all the employees detail*/
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
Address add = employee.getAddress();
System.out.println("Address ");
System.out.println("\tStreet: " + add.getStreet());
System.out.println("\tCity: " + add.getCity());
System.out.println("\tState: " + add.getState());
System.out.println("\tZipcode: " + add.getZipcode());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/*Method to update salary for an employee*/
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
コンパイルと実行
上記のアプリケーションをコンパイルして実行する手順は次のとおりです。 コンパイルと実行に進む前に、PATHとCLASSPATHが適切に設定されていることを確認してください。
- 構成の章で説明されているように、hibernate.cfg.xml構成ファイルを作成します。
- 上記のように、Employee.hbm.xmlマッピングファイルを作成します。
- 上記のようにEmployee.javaソースファイルを作成し、コンパイルします。
- 上記のようにAddress.javaソースファイルを作成し、コンパイルします。
- 上記のようにManageEmployee.javaソースファイルを作成し、コンパイルします。 *ManageEmployeeバイナリを実行してプログラムを実行します。
画面に次の結果が表示されると同時に、EMPLOYEEおよびADDRESSテーブルにレコードが作成されます。
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Manoj Last Name: Kumar Salary: 4000
Address
Street: Kondapur
City: Hyderabad
State: AP
Zipcode: 532
First Name: Dilip Last Name: Kumar Salary: 3000
Address
Street: Saharanpur
City: Ambehta
State: UP
Zipcode: 111
First Name: Manoj Last Name: Kumar Salary: 5000
Address
Street: Kondapur
City: Hyderabad
State: AP
Zipcode: 532
First Name: Dilip Last Name: Kumar Salary: 3000
Address
Street: Saharanpur
City: Ambehta
State: UP
Zipcode: 111
あなたはあなたの従業員とCERTIFICATEテーブルをチェックする場合、それらは次のレコードを持つ必要があります-
mysql> select* from EMPLOYEE;
+----+------------+-----------+--------+---------+
| id | first_name | last_name | salary | address |
+----+------------+-----------+--------+---------+
| 7 | Manoj | Kumar | 5000 | 5 |
| 8 | Dilip | Kumar | 3000 | 6 |
+----+------------+-----------+--------+---------+
2 rows in set (0.00 sec)
mysql> select * from ADDRESS;
+----+-------------+-----------+------------+---------+
| id | street_name | city_name | state_name | zipcode |
+----+-------------+-----------+------------+---------+
| 5 | Kondapur | Hyderabad | AP | 532 |
| 6 | Saharanpur | Ambehta | UP | 111 |
+----+-------------+-----------+------------+---------+
2 rows in set (0.00 sec)
mysql>