- 浏览: 23422 次
最近访客 更多访客>>
最新评论
-
linginfanta:
没有翻完。
转贴 java 泛型,辛苦译者了 -
阳光晒晒:
等四五小时再看,如果内存下来了
一般是由于数据库连接没关闭.
...
J2EE 系统 outofmemory问题 -
anxin587:
今天一直用jprofiler来跟踪,发现一个奇怪的问题,当to ...
J2EE 系统 outofmemory问题
在域模型中,类之间最普遍的关系是关联关系,关联是有方向的,分为单向关联和双向关联,在关系数据库中,为了避免冗余,只存在many 方参照one方,所以关系数据库实际上面是多对一,一对一的单向关联,
在类和类之间各种关系中,多对一的单向关联和关系数据库的外键参照关系最匹配,下面一个简单例子来说明这些
两个实体,分别为Customer和orders,同时一个customer可以拥有0个或者多个orders,他们的DDL如下所示
CREATE TABLE CUSTOMERS (ID INT AUTO_INCREMENT PRIMARY KEY,NAME VARCHAR(20))
CREATE TABLE ORDERS
(
ID INT AUTO_INCREMENT PRIMARY KEY,
CUSTOMER_ID INT,
ORDERNUMBER INT,
CONSTRAINT FK FOREIGN KEY(CUSTOMER_ID) REFERENCES CUSTOMERS(ID)
)
Customer类如下
package entity;
import java.util.*;
public class Customer
{
private Long id;
private String name;
private Set orders=new HashSet();
private void setId(Long id)
{
this.id=id;
}
public Long getId()
{
return this.id;
}
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
public void setOrders(Set orders)
{
this.orders=orders;
}
public Set getOrders()
{
return this.orders;
}
}
orders类如下
package entity;
public class Order
{
private Long id;
private Customer customer;
private int ordernumber;
private void setId(Long id)
{
this.id=id;
}
public Long getId()
{
return this.id;
}
public void setCustomer(Customer customer)
{
this.customer=customer;
}
public Customer getCustomer()
{
return this.customer;
}
public void setOrdernumber(int ordernumber)
{
this.ordernumber=ordernumber;
}
public int getOrdernumber()
{
return this.ordernumber;
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="entity">
<class name="Order" table="ORDERS">
<id name="id" column="ID">
<generator class="increment"/>
</id>
<property name="ordernumber" column="ORDERNUMBER"/>
<many-to-one name="customer" column="CUSTOMER_ID" class="Customer" cascade="save-update"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="entity">
<class name="Customer" table="CUSTOMERS">
<id name="id" column="ID">
<generator class="increment"/>
</id>
<property name="name" type="string" column="NAME"/>
<set name="orders" cascade="delete">
<key column="CUSTOMER_ID"/>
<one-to-many class="Order"/>
</set>
</class>
package service;
import util.*;
import entity.*;
import org.hibernate.*;
import java.util.*;
public class Test
{
public static void saveCustomerAndOrder()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=new Customer();
customer.setName("andy");
session.save(customer);
Order order=new Order();
Order order1=new Order();
order.setOrdernumber(1);
order.setCustomer(customer);
order1.setOrdernumber(2);
order1.setCustomer(customer);
session.save(order);
session.save(order1);
session.getTransaction().commit();
}
public static void saveCustomerAndOrderWithCascade()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=new Customer();
customer.setName("cao");
//session.save(customer);
Order order=new Order();
Order order1=new Order();
order.setOrdernumber(1);
order.setCustomer(customer);
order1.setOrdernumber(2);
order1.setCustomer(customer);
session.save(order);
session.save(order1);
session.getTransaction().commit();
}
public static Customer getCustomerThOrder()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=((Order)session.load(Order.class,new Long(1))).getCustomer();
session.getTransaction().commit();
if(customer!=null)
return customer;
return null;
}
public static Set getOrderThCustomer()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Set orders=((Customer)session.load(Customer.class,new Long(1))).getOrders();
session.getTransaction().commit();
if(orders.size()>0)
return orders;
return null;
}
public static void updateCustomerAndOrders()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
Order order = (Order)session.load(Order.class,new Long(3));
order.setCustomer(customer);
customer.getOrders().add(order);
session.getTransaction().commit();
}
public static void delCustomer()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
session.delete(customer);
session.getTransaction().commit();
}
public static void main(String[] args)
{
Test.delCustomer();
//Customer cst=Test.getCustomerThOrder();
//System.out.println(cst.getName());
//Test.updateCustomerAndOrders();
/*
Set orders=Test.getOrderThCustomer();
Iterator it=null;
for(it=orders.iterator();it.hasNext();)
{
Order order=(Order)it.next();
System.out.println(order.getId()+" || "+order.getOrdernumber()+" || "+order.getCustomer().getName());
}
//*/
//Test.saveCustomerAndOrderWithCascade();
//System.out.println( HibernateUtil.getSessionFactory());
}
}
</hibernate-mapping>
建立多对一的单向关联,也就是在order类里面建立到customer的关联,即在order类里面增加customer属性,这样通过order类即可以获得与之对应的customer信息,同时配置文件里面增加
<many-to-one name="customer" // 为order类里面增加的属性的名称
column=‘customer id’这个是外键的列的名称
class =“mypack。customer” 这个是外键所关联的那一个类 >
name:设定待映射的持久化类的属性名 column:设定和持久化类的属性对应的表的外键, class 设定持久化类的属性类型
这样建立的单向关联就可以进行单向的访问,
public static void saveCustomerAndOrder()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=new Customer();
customer.setName("andy");
session.save(customer);
Order order=new Order();
Order order1=new Order();
order.setOrdernumber(1);
order.setCustomer(customer);
order1.setOrdernumber(2);
order1.setCustomer(customer);
session.save(order);
session.save(order1);
session.getTransaction().commit();
}
上面的方法就是先保存customer然后在保存orders,其中order多属于customer的,如果我们仅仅是定义了customer对象不对它进行持久化,而我们又象对order进行持久化这样就会违背数据库的参照完整性,所以hibernate会抛出相应的异常,
org.hibernate.PropertyValueException : not-null property references a null or transientvalue 也就是告诉我们说order类的customer属性是不允许为空的 ,我们可以设定级联保存和更新来解决这个问题,
<many-to-one name="customer" column="CUSTOMER_ID" class="Customer" cascade="save-update"/>
在hibernate持久化一个临时对象(transient object)对象时,它不会自动持久化所关联的其他临时对象,这样就会抛出我们上面的那个异常,我们设定cascade为save-update,默认是none,这样保存orders的同时会先保存customer。
通过多对一的单向关联,我们可以通过order很容易的获得customer信息,但是如果反过来,现在我们需要根据customer信息来获得order信息,所以这样的时候,我们需要建立一对多的双向关联在customer类里面增加Set orders并且给出对应的get set方法,然后在hbmxml里面增加
<set name="orders">//这个是customer类里面的属性的名称
<key column="customer_id"/> 元素设定与所关联的持久化类对应的表的外键
<one-to -many class="order"/> 设定所关联的持久化类,此处为orders
</set>
通过这些我们就可以根据customer来获得自己的orders信息了,上面配置注意点:不要巴一个单元故意用enter来分成多行显示,否则会出现error
set元素的inverse
public static void updateCustomerAndOrders()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
Order order = (Order)session.load(Order.class,new Long(3));
order.setCustomer(customer);
customer.getOrders().add(order);
session.getTransaction().commit();
}
上面这个update方法在hibernate中实际上面是执行了两句sql语句update orders set ordernumber='aaaa' customerid='2' where customerid='2' , update orders set customerid=2 where id=2,
因为hibernate是根据内存中持久化对象的状态变化来决定需要执行那些sql语句的。inverse=true加上以后则表明customer端的关联只是order端关联的镜像,这样的话,就只会执行一条sql语句
<set name="orders" cascade="delete" inverse="true">
<key column="CUSTOMER_ID"/>
<one-to-many class="Order"/>
</set>
public static void updateCustomerAndOrders()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class,new Long(1));
Order order = (Order)session.load(Order.class,new Long(3));
??order.setCustomer(customer); 如果保留这一句会去更新database
//customer.getOrders().add(order); 如果只保留这句的话数据库并不会被更新
session.getTransaction().commit();
}
所以这就要求我们最好在写代码的时候写好双向关联的代码,提高程序的健壮性,而不去依赖底层的数据库或者hibernate来解决这些问题,一般情况下many端的inverse设成true,在上面的应用中也就是customer端,好像这里说many端会有些迷惑,向这set端就对了
映射一对多自身双向关联,上一个项目中就有这样的情况,一个公司 公司有0个或1个自己的母公司,当然一个公司也就可能容有0个或n个子公司,这样数据库设计一般为
create table company( id int auto_increment primary key,name varchar(20), Company_id int
constraint fk company_id references company(id));
也就是公司表里面有一个属性关联着自己的主键,自身关联
package entity;
import java.util.*;
public class Company
{
private Long id;
private String name;
private Company company;
private Set companys=new HashSet();
private void setId(Long id)
{
this.id=id;
}
public Long getId()
{
return this.id;
}
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
public void setCompany(Company company)
{
this.company=company;
}
public Company getCompany()
{
return this.company;
}
public void setCompanys(Set companys)
{
this.companys=companys;
}
public Set getCompanys()
{
return this.companys;
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="entity">
<class name="Company" table="COMPANY">
<id name="id" column="ID">
<generator class="increment"/>
</id>
<property name="name" column="NAME" type="string"/>
<many-to-one name="company" column="COMPANY_ID" class="Company" cascade="save-update"/>
<set name="companys">
<key column="COMPANY_ID"/>
<one-to-many class="Company"/>
</set>
</class>
</hibernate-mapping>
public static void saveCompany()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Company company=new Company();
company.setName("anxin_2");
company.setCompany((Company)session.load(Company.class,new Long(1)));
session.save(company);
session.getTransaction().commit();
}
public static String findVdrCompany()
{
Session session=HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Company company=(Company)session.load(Company.class,new Long(2));
String r=company.getCompany().getName();
session.getTransaction().commit();
return r;
}
上面就是自身关联相关的代码,但是有一个注意就是不要给里面的那个外键设定notnull,要不永远也加不进去数据了,呵呵
发表评论
-
hibernate初级 映射复合自然主键
2007-09-13 22:53 1455现在根据customer和orders ... -
hibernate初级 对象-映射组成关系
2007-09-09 22:21 1150域对象中,类之间存在四种关系,1关联,也就是类之间的引用关系, ... -
hibernate初级 hibernate中对象的状态及其相互关系
2007-09-09 15:27 1418在java中应用程序通过new创建一个java对象时,jvm会 ... -
hibernate初级 映射对象标识符
2007-09-05 23:35 1850Hibernate使用对象标识符来建立内存中的对象和数据库表中 ... -
hibernate初级 对象-关系映射基础
2007-09-04 22:45 1270学习精通Hibernate java对象持久化第4章联系如下: ...
相关推荐
Hibernate映射一对多关联关系
包含《多对多双向关联映射》《多对一单向关联映射》《多对一双向关联映射》《一对多单向关联映射》等文档,并有图解及例子,非常适合新手学习,尤其是刚刚接触hibernate,对映射关系不清楚的。。。。
Hibernate 多对一外键单向关联 Hibernate 多对一连接表单向关联 Hibernate 多对多单向关联 Hibernate 一对一外键双向关联 Hibernate 一对一主键双向关联 Hibernate 一对一连接表双向关联 Hibernate 一对多外键双向...
hibernate关联映射详解SSH 多对多,一对多关系对象映射
Hibernate4中映射关系图解。
Hibernate关联关系映射 单向关联 │ ├─ 一对一外键单向关联 │ ├─ 一对一主键单向关联 │ ├─ 一对一连接表单向关联 │ ├─ 一对多外键单向关联 │ ├─ 一对多连接表单向关联 │ ├─ 多对一外键单向关联 │ ...
Hibernate双向一对一关联映射(注解版)
这里包含了hibernate多对一单向关联关系实现源码,希望对你有用。
该资源包含了一些常用的hibernate关联映射实例。包括一对多,多对多,继承映射,等,是学习hibernate的必备品
NULL 博文链接:https://1028826685.iteye.com/blog/1536060
student与Score的Map集合关系 student与class的多对一 一对多映射
1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1:一对多和多对一映射,举例说明: 学生和老师: 一个老师可以教多个学生 【一对多映射】 多个学生可以被一个老师教【多对一映射】 部门与员工: ...
hibernate双向一对多关联映射(注解版)
Hibernate 关联关系映射分类
关于对Hibernate关联映射的一个总结,其中有各种映射的例子,详细用法 等
hibernate 对象关系映射总结hibernate 对象关系映射总结hibernate 对象关系映射总结
hibernate外键实现一对一双向关联关系源码
hibernate主键实现一对一单向关联关系源码
博文链接:https://shaqiang32.iteye.com/blog/201309
hibernate实现多对多关联关系源码