映射一对多关联关系
以Customer和Order为例:
一对多:
每个Customer可以有一个或者多个Order,因此Customer中应该有一个集合类型的属性,来引用所有关联的Order对象。
多对一:
Order到Customer的关联为多对一关联,每个Order对象都要有一个Customer对象。在Order中要有一个Customer类型的属性。
如果仅包含Customer到Order或者仅包含Order呆Customer的关联,就叫做单向关联。
同时包含两个关联的就坐双向关联。
第一部分:
以
Order
和
Customer
为例,介绍如何映射多对一单向关联关系。
这个例子的特点是只在Order中加入Customer属性,建立单向关联。
1 数据库:
alter table ORDERS drop foreign key FK8B7256E516B4891C;
drop table if exists CUSTOMERS;
drop table if exists ORDERS;
create table CUSTOMERS (
ID bigint not null,
NAME varchar(15),
primary key (ID)
);
create table ORDERS (
ID bigint not null,
ORDER_NUMBER varchar(15),
CUSTOMER_ID bigint not null,
primary key (ID)
);
alter table ORDERS add index FK8B7256E516B4891C (CUSTOMER_ID), add constraint FK8B7256E516B4891C foreign key (CUSTOMER_ID) references CUSTOMERS (ID);
2 类
Customers.java
package
mypack;
import
java.util.HashSet;
import
java.util.Set;
/**
*
Customers
generated
by
MyEclipse
Persistence
Tools
*/
public
class
Customers
implements
java.io.Serializable {
// Fields
private
Long
id
;
private
String
name
;
// Constructors
/**
default
constructor
*/
public
Customers() {
}
/**
full
constructor
*/
public
Customers(String name) {
this
.
name
= name;
}
// Property accessors
public
Long getId() {
return
this
.
id
;
}
public
void
setId(Long id) {
this
.
id
= id;
}
public
String getName() {
return
this
.
name
;
}
public
void
setName(String name) {
this
.
name
= name;
}
}
Orders.java
package
mypack;
/**
*
Orders
generated
by
MyEclipse
Persistence
Tools
*/
public
class
Orders
implements
java.io.Serializable {
// Fields
private
Long
id
;
private
Customers
customers
;
private
String
orderNumber
;
// Constructors
/**
default
constructor
*/
public
Orders() {
}
/**
minimal
constructor
*/
public
Orders(Customers customers) {
this
.
customers
= customers;
}
/**
full
constructor
*/
public
Orders(Customers customers, String orderNumber) {
this
.
customers
= customers;
this
.
orderNumber
= orderNumber;
}
// Property accessors
public
Long getId() {
return
this
.
id
;
}
public
void
setId(Long id) {
this
.
id
= id;
}
public
Customers getCustomers() {
return
this
.
customers
;
}
public
void
setCustomers(Customers customers) {
this
.
customers
= customers;
}
public
String getOrderNumber() {
return
this
.
orderNumber
;
}
public
void
setOrderNumber(String orderNumber) {
this
.
orderNumber
= orderNumber;
}
}
测试类:
BusinessService.java
package
mypack;
import
java.util.Iterator;
import
java.util.List;
import
org.hibernate.Query;
import
org.hibernate.Session;
import
org.hibernate.Transaction;
import
com.sun.org.apache.xpath.internal.operations.Or;
import
sessionFactory.HibernateSessionFactory;
public
class
BusinessService {
public
List findOrdersByCustomer(Customers customer)
throws
Exception {
Session session =
null
;
Transaction tr =
null
;
try
{
session = HibernateSessionFactory.getSession();
tr = session.beginTransaction();
Query query = session
.createQuery(
"from Orders as o where o.customers.id="
+ customer.getId());
List orders = query.list();
tr.commit();
return
orders;
}
catch
(Exception e) {
//
TODO
: handle exception
if
(tr !=
null
) {
tr.rollback();
}
throw
e;
}
finally
{
session.close();
}
}
public
Customers findCustomer(Long customer_id)
throws
Exception {
Session session =
null
;
Transaction tr =
null
;
try
{
session = HibernateSessionFactory.getSession();
tr = session.beginTransaction();
Customers customer = (Customers) session.load(Customers.
class
,
customer_id);
tr.commit();
return
customer;
}
catch
(Exception e) {
//
TODO
: handle exception
if
(tr !=
null
) {
tr.rollback();
}
throw
e;
}
finally
{
session.close();
}
}
public
void
saveCustomerAndOrder()
throws
Exception {
Session session =
null
;
Transaction tr =
null
;
try
{
session = HibernateSessionFactory.getSession();
tr = session.beginTransaction();
Customers customer =
new
Customers(
"zhang"
);
session.save(customer);
Orders order1 =
new
Orders(customer,
"order1"
);
Orders order2 =
new
Orders(customer,
"order2"
);
session.save(order1);
session.save(order2);
tr.commit();
}
catch
(Exception e) {
//
TODO
: handle exception
if
(tr !=
null
) {
tr.rollback();
}
throw
e;
}
finally
{
session.close();
}
}
public
void
saveCustomerAndOrdeWithCascader()
throws
Exception {
Session session =
null
;
Transaction tr =
null
;
try
{
session = HibernateSessionFactory.getSession();
tr = session.beginTransaction();
Customers
customer
=
new
Customers(
"zhang"
);
// session.save(customer);//
映射文件中加入
cascade="save-update"
Orders order1 =
new
Orders(customer,
"order1"
);
Orders order2 =
new
Orders(customer,
"order2"
);
session.save(order1);
session.save(order2);
tr.commit();
}
catch
(Exception e) {
//
TODO
: handle exception
if
(tr !=
null
) {
tr.rollback();
}
throw
e;
}
finally
{
session.close();
}
}
public
void
printOrders(List orders) {
for
(Iterator it = orders.iterator(); it.hasNext();) {
Orders order = (Orders) it.next();
System.
out
.println(
"OrderNumber of "
+ order.getCustomers().getName() +
" :"
+ order.getOrderNumber());
}
}
public
void
test()
throws
Exception {
saveCustomerAndOrder();
saveCustomerAndOrdeWithCascader();
Customers customer = findCustomer(
new
Long(1));
List orders = findOrdersByCustomer(customer);
printOrders(orders);
}
/**
*
@param
args
*
@throws
Exception
*/
public
static
void
main(String[] args)
throws
Exception {
//
TODO
Auto-generated method stub
BusinessService b =
new
BusinessService();
b.test();
}
}
3 映射文件:
Customers.hbm.xml
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<!
DOCTYPE
hibernate-mapping
PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<
hibernate-mapping
>
<
class
name
=
"mypack.Customers"
table
=
"customers"
catalog
=
"onetomany"
lazy
=
"false"
>
<
id
name
=
"id"
type
=
"java.lang.Long"
>
<
column
name
=
"ID"
/>
<
generator
class
=
"increment"
/>
</
id
>
<
property
name
=
"name"
type
=
"java.lang.String"
>
<
column
name
=
"NAME"
length
=
"15"
/>
</
property
>
</
class
>
</
hibernate-mapping
>
Orders.hbm.xml
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<!
DOCTYPE
hibernate-mapping
PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<
hibernate-mapping
>
<
class
name
=
"mypack.Orders"
table
=
"orders"
catalog
=
"onetomany"
>
<
id
name
=
"id"
type
=
"java.lang.Long"
>
<
column
name
=
"ID"
/>
<
generator
class
=
"increment"
/>
</
id
>
<
many-to-one
name
=
"customers"
class
=
"mypack.Customers"
fetch
=
"select"
cascade
=
"save-update"
>
<
column
name
=
"CUSTOMER_ID"
not-null
=
"true"
/>
</
many-to-one
>
<
property
name
=
"orderNumber"
type
=
"java.lang.String"
>
<
column
name
=
"ORDER_NUMBER"
length
=
"15"
/>
</
property
>
</
class
>
</
hibernate-mapping
>
小结:本例子的重点是级联保存和更新的使用。当建立了Order到Customer的单向关联时,把映射文件中的<many-to-one>的cascade属性设置为save-update,只做保存Order的操作,与Order对应的customer对象就自动被保存了。(前提是在测试的文件中加入了对Order的Customer属性的设置)