List映射表
List列表是一個java集合存儲在序列中的元素,并允許重復的元素。此接口的用戶可以精確地控制,其中列表中的每個元素插入。用戶可以通過他們的整數索引訪問元素,并搜索列表中的元素。更正式地說,列表通常允許對元素e1和e2,使得e1.equals(e2),它們通常允許多個null元素,如果他們允許的null元素。
List列表被映射在該映射表中的<list>元素,并將java.util.ArrayList中初始化。
定義RDBMS表:
考慮一個情況,需要員工記錄存儲在EMPLOYEE表,將有以下結構:
1
2
3
4
5
6
7
|
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 , PRIMARY KEY (id) ); |
此外,假設每個員工都可以有一個或多個與他/她相關的證書。List集合映射需要在一個集合表的索引列。索引列定義集合中的元素的位置。因此,我們將存儲證書的相關信息在一個單獨的表,該表具有以下結構:
1
2
3
4
5
6
7
|
create table CERTIFICATE ( id INT NOT NULL auto_increment, certificate_name VARCHAR (30) default NULL , idx INT default NULL , employee_id INT default NULL , PRIMARY KEY (id) ); |
將有一個對多( one-to-many)的EMPLOYEE和證書對象之間的關系。
定義POJO類:
讓我們實現一個POJO類員工將被用于保存與EMPLOYEE表中的對象和有證書的列表變量的集合。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
import java.util.*; public class Employee { private int id; private String firstName; private String lastName; private int salary; private List certificates; public Employee() {} public Employee(String fname, String lname, int salary) { this .firstName = fname; this .lastName = lname; this .salary = salary; } 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 List getCertificates() { return certificates; } public void setCertificates( List certificates ) { this .certificates = certificates; } } |
我們需要相應的證書表定義另一個POJO類,這樣的證書對象可以存儲和檢索到的證書表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class Certificate{ private int id; private String name; public Certificate() {} public Certificate(String name) { this .name = name; } public int getId() { return id; } public void setId( int id ) { this .id = id; } public String getName() { return name; } public void setName( String name ) { this .name = name; } } |
定義Hibernate映射文件:
讓我們開發指定Hibernate如何定義的類映射到數據庫表的映射文件。<list>元素將被用來定義使用List集合的規則。表的索引是整數類型總是和使用<list-index>元素定義映射。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<? 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 > < list name = "certificates" cascade = "all" > < key column = "employee_id" /> < list-index column = "idx" /> < one-to-many class = "Certificate" /> </ list > < property name = "firstName" column = "first_name" type = "string" /> < property name = "lastName" column = "last_name" type = "string" /> < property name = "salary" column = "salary" type = "int" /> </ class > < class name = "Certificate" table = "CERTIFICATE" > < meta attribute = "class-description" > This class contains the certificate records. </ meta > < id name = "id" type = "int" column = "id" > < generator class = "native" /> </ id > < property name = "name" column = "certificate_name" type = "string" /> </ class > </ hibernate-mapping > |
應該保存的映射文件中的格式<classname>.hbm.xml。我們保存我們的映射文件中的文件Employee.hbm.xml。你已經熟悉了大部分的映射細節,映射文件中的所有元素:
映射文檔是具有<hibernate-mapping>為對應于每一個類包含2個<class>元素的根元素的XML文檔。
<class>元素被用于定義數據庫表從一個Java類特定的映射。 Java類名指定使用class元素的name屬性和使用表屬性數據庫表名指定。
<meta>元素是可選元素,可以用來創建類的描述。
<id>元素映射在類中的唯一ID屬性到數據庫表的主鍵。 id元素的name屬性是指屬性的類和column屬性是指在數據庫表中的列。 type屬性保存了Hibernate映射類型,這種類型的映射將會從Java轉換為SQL數據類型。
id元素內的<generator>元素被用來自動生成的主鍵值。將生成元素的class屬性設置為原生讓Hibernate拿起無論是identity,sequence或者hilo中的算法來創建主鍵根據底層數據庫的支持能力。
<property>元素用于一個Java類的屬性映射到數據庫表中的列。元素的name屬性是指屬性的類和column屬性是指在數據庫表中的列。 type屬性保存了Hibernate映射類型,這種類型的映射將會從Java轉換為SQL數據類型。
<list>元素用于設置證書和Employee類之間的關系。我們使用cascade屬性中<list>元素來告訴Hibernate來保存證書的對象,同時為Employee對象。 name屬性被設置為在父類中定義的Listvariable,在我們的情況下,它是證書。
<key>元素是包含外鍵的父對象,即在證書表中的列。即,表EMPLOYEE。
<list-index>元素定義用于保持元件的位置,并與在該集合表的索引列映射。持久性列表的索引從零開始。你可以改變這一點,例如,在你的映射<list-index base="1".../>。
<one-to-many>元素表示一個Employee對象涉及到很多證書的對象,并因此,證書對象必須有與之勞動者家長有關。您可以根據您的需要使用任何和<one-to-one>,<many-to-one>進行或<many-to-many>這個元素。如果我們改變了這個例子使用一個many-to-many的關系,我們需要一個關聯表到父和子對象之間的映射。
創建應用程序類:
最后,我們將創建應用程序類的main()方法來運行應用程序。我們將使用這個應用程序,以節省一些員工的記錄連同的證書,然后我們將申請CRUD操作上的記錄。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
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 a set of certificates for the first employee */ ArrayList set1 = new ArrayList(); set1.add(new Certificate("MCA")); set1.add(new Certificate("MBA")); set1.add(new Certificate("PMP")); /* Add employee records in the database */ Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, set1); /* Another set of certificates for the second employee */ ArrayList set2 = new ArrayList(); set2.add(new Certificate("BCA")); set2.add(new Certificate("BA")); /* Add another employee record in the database */ Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, set2); /* List down all the employees */ ME.listEmployees(); /* Update employee's salary records */ ME.updateEmployee(empID1, 5000); /* Delete an employee from the database */ ME.deleteEmployee(empID2); /* List down all the employees */ ME.listEmployees(); } /* Method to add an employee record in the database */ public Integer addEmployee(String fname, String lname, int salary, ArrayList cert){ Session session = factory.openSession(); Transaction tx = null; Integer employeeID = null; try{ tx = session.beginTransaction(); Employee employee = new Employee(fname, lname, salary); employee.setCertificates(cert); 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 iterator1 = employees.iterator(); iterator1.hasNext();){ Employee employee = (Employee) iterator1.next(); System.out.print("First Name: " + employee.getFirstName()); System.out.print(" Last Name: " + employee.getLastName()); System.out.println(" Salary: " + employee.getSalary()); List certificates = employee.getCertificates(); for (Iterator iterator2 = certificates.iterator(); iterator2.hasNext();){ Certificate certName = (Certificate) iterator2.next(); System.out.println("Certificate: " + certName.getName()); } } 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(); } } /* Method to delete an employee from the records */ public void deleteEmployee(Integer EmployeeID){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); Employee employee = (Employee)session.get(Employee. class , EmployeeID); session.delete(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源文件,如上圖所示,并編譯它.
- 創建Certificate.java源文件,如上圖所示,并編譯它。
- 創建ManageEmployee.java源文件,如上圖所示,并編譯它。
- 執行ManageEmployee二進制文件來運行程序。
會在屏幕上獲得以下結果,并同時記錄會在員工和證書表被創建。可以看到證書已排序順序相反。可以通過改變映射文件試試,只需設置sort="natural"和執行程序,并比較結果。
1
|
$java ManageEmployee |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........ First Name: Manoj Last Name: Kumar Salary: 4000 Certificate: MCA Certificate: MBA Certificate: PMP First Name: Dilip Last Name: Kumar Salary: 3000 Certificate: BCA Certificate: BA First Name: Manoj Last Name: Kumar Salary: 5000 Certificate: MCA Certificate: MBA Certificate: PMP |
如果檢查員工和證書表,就應該記錄下了:
1
|
mysql> select * from EMPLOYEE; |
1
2
3
4
5
6
|
+----+------------+-----------+--------+ | id | first_name | last_name | salary | +----+------------+-----------+--------+ | 51 | Manoj | Kumar | 5000 | +----+------------+-----------+--------+ 1 row in set (0.00 sec) |
1
|
mysql> select * from CERTIFICATE; |
1
2
3
4
5
6
7
8
|
+----+------------------+------+-------------+ | id | certificate_name | idx | employee_id | +----+------------------+------+-------------+ | 6 | MCA | 0 | 51 | | 7 | MBA | 1 | 51 | | 8 | PMP | 2 | 51 | +----+------------------+------+-------------+ 3 rows in set (0.00 sec) |
或者,您也可以映射Java數組,而不是一個列表。一個數組的映射幾乎是相同的前面的例子,除了與不同的元素和屬性名稱(<array>和<array-index>)。然而,原因如前所述,Hibernate應用程序很少使用數組。
Bag映射
Bag是一個java集合存儲元素無需關心順序,但允許列表中的重復元素。Bag是在列表中的對象的隨機分組。
Collection集合被映射在該映射表中的<bag>元件和與java.util.ArrayList中初始化。
下面的示例中RDBMS表和POJO類依然使用上面定義好的。
定義Hibernate映射文件:
讓我們開發指示Hibernate如何定義的類映射到數據庫表的映射文件。<bag>元素將被用來定義所使用的集合規則。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<? 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 > < bag name = "certificates" cascade = "all" > < key column = "employee_id" /> < one-to-many class = "Certificate" /> </ bag > < property name = "firstName" column = "first_name" type = "string" /> < property name = "lastName" column = "last_name" type = "string" /> < property name = "salary" column = "salary" type = "int" /> </ class > < class name = "Certificate" table = "CERTIFICATE" > < meta attribute = "class-description" > This class contains the certificate records. </ meta > < id name = "id" type = "int" column = "id" > < generator class = "native" /> </ id > < property name = "name" column = "certificate_name" type = "string" /> </ class > </ hibernate-mapping > |
應該保存的映射文件中的格式<classname>.hbm.xml。我們保存映射文件Employee.hbm.xml。前面已經熟悉了大部分的映射細節,但讓我們看到了映射文件中的所有元素再次:
映射文檔是具有<hibernate-mapping>為對應于每一個類包含2個<class>元素的根元素的XML文檔。
<class>元素被用于定義數據庫表從一個Java類特定的映射。 Java類名指定使用class元素的name屬性和使用表屬性數據庫表名指定。
<meta>元素是可選元素,可以用來創建類的描述。
<id>元素映射在類中的唯一ID屬性到數據庫表的主鍵。 id元素的name屬性是指屬性的類和column屬性是指在數據庫表中的列。 type屬性保存了Hibernate映射類型,這種類型的映射將會從Java轉換為SQL數據類型。
id元素內的<generator>元素被用來自動生成的主鍵值。將生成元素的class屬性設置為原生讓Hibernate拿起無論是identity,sequence或者hilo中的算法來創建主鍵根據底層數據庫的支持能力。
<property>元素用于一個Java類的屬性映射到數據庫表中的列。元素的name屬性是指屬性的類和column屬性是指在數據庫表中的列。 type屬性保存了Hibernate映射類型,這種類型的映射將會從Java轉換為SQL數據類型。
<bag>元素用于設置證書和Employee類之間的關系。我們使用cascade屬性的<bag>高的元素要告訴Hibernate來保存證書的對象,同時為Employee對象。 name屬性被設置為在父類中的definedCollection變量,在我們的情況下,它是證書。
<key>元素是包含外鍵的父對象,即在證書表中的列。表EMPLOYEE。
<one-to-many>元素表示一個Employee對象涉及到很多證書的對象,并因此,證書對象必須有與Employee父類有關聯。可以根據需要使用<one-to-one>,<many-to-one>或<many-to-many>這個元素。
創建應用程序類:
最后,我們將創建應用程序類的main()方法來運行應用程序。我們將使用這個應用程序,以節省一些員工的記錄連同的證書,然后我們將申請CRUD操作上的記錄。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
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 a set of certificates for the first employee */ ArrayList set1 = new ArrayList(); set1.add(new Certificate("MCA")); set1.add(new Certificate("MBA")); set1.add(new Certificate("PMP")); /* Add employee records in the database */ Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, set1); /* Another set of certificates for the second employee */ ArrayList set2 = new ArrayList(); set2.add(new Certificate("BCA")); set2.add(new Certificate("BA")); /* Add another employee record in the database */ Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, set2); /* List down all the employees */ ME.listEmployees(); /* Update employee's salary records */ ME.updateEmployee(empID1, 5000); /* Delete an employee from the database */ ME.deleteEmployee(empID2); /* List down all the employees */ ME.listEmployees(); } /* Method to add an employee record in the database */ public Integer addEmployee(String fname, String lname, int salary, ArrayList cert){ Session session = factory.openSession(); Transaction tx = null; Integer employeeID = null; try{ tx = session.beginTransaction(); Employee employee = new Employee(fname, lname, salary); employee.setCertificates(cert); 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 iterator1 = employees.iterator(); iterator1.hasNext();){ Employee employee = (Employee) iterator1.next(); System.out.print("First Name: " + employee.getFirstName()); System.out.print(" Last Name: " + employee.getLastName()); System.out.println(" Salary: " + employee.getSalary()); Collection certificates = employee.getCertificates(); for (Iterator iterator2 = certificates.iterator(); iterator2.hasNext();){ Certificate certName = (Certificate) iterator2.next(); System.out.println("Certificate: " + certName.getName()); } } 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(); } } /* Method to delete an employee from the records */ public void deleteEmployee(Integer EmployeeID){ Session session = factory.openSession(); Transaction tx = null ; try { tx = session.beginTransaction(); Employee employee = (Employee)session.get(Employee. class , EmployeeID); session.delete(employee); tx.commit(); } catch (HibernateException e) { if (tx!= null ) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } } |
編譯和執行:
會在屏幕上獲得以下結果,并同時記錄會在員工和證書表被創建。可以看到證書已排序順序相反。可以通過改變映射文件試試,只需設置sort="natural"和執行程序,并比較結果。
1
|
$java ManageEmployee |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........ First Name: Manoj Last Name: Kumar Salary: 4000 Certificate: MCA Certificate: MBA Certificate: PMP First Name: Dilip Last Name: Kumar Salary: 3000 Certificate: BCA Certificate: BA First Name: Manoj Last Name: Kumar Salary: 5000 Certificate: MCA Certificate: MBA Certificate: PMP |
如果檢查員工和證書表,就應該記錄下了:
1
|
mysql> select * from EMPLOYEE; |
1
2
3
4
5
6
|
+----+------------+-----------+--------+ | id | first_name | last_name | salary | +----+------------+-----------+--------+ | 53 | Manoj | Kumar | 5000 | +----+------------+-----------+--------+ 1 row in set (0.00 sec) |
1
|
mysql> select * from CERTIFICATE; |
1
2
3
4
5
6
7
8
|
+----+------------------+-------------+ | id | certificate_name | employee_id | +----+------------------+-------------+ | 11 | MCA | 53 | | 12 | MBA | 53 | | 13 | PMP | 53 | +----+------------------+-------------+ 3 rows in set (0.00 sec) |