欢迎访问:我的个人网站
一对多级联操作
##1.级联插入操作
继续引用上篇所建立的一对多映射关系,在本例中尝试插入一个消费者以及一个地址,首先可以使用如下的方式进行:
- 分别创建实体对象Customer以及地址实体Address,并为其设置值。
- 为两个实体建立彼此的关系
- 将两个对象持久化
代码如下:
@Test
public void test(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.getCurrentSession();
transaction = session.getTransaction();
transaction.begin();
//建立一个消费者并设置属性
Customer customer = new Customer();
customer.setName("AA");
//建立地址并设置地址
Address address = new Address();
address.setAddress("云南大理");
//为二者建立关系,消费者为1端,可以有多个地址对象,地址实体为N端,仅可以属于一个消费者
address.setCustomer(customer);//设置该地址所对应唯一的消费者对象
customer.getAddressSet().add(address);//设置消费者所对应的地址,这里只添加了一个地址,可以添加多个
//持久化
session.save(customer);
session.save(address);
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
if(sessionFactory!=null){
sessionFactory.close();
}
}
}
按照以上的步骤就可以将两个对象持久化到数据库。当前实体的属性还非常少,如果非常多的话上面的方法就显得有些繁琐,所以我们还可以用下面的一种方式进行插入操作,针对插入操作,需要在1端(消费者实体)的set标签设置属性 cascade="save-update 大致流程如下:
@Test
public void test(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.getCurrentSession();
transaction = session.getTransaction();
transaction.begin();
//建立一个消费者并设置属性
Customer customer = new Customer();
customer.setName("AA");
//建立地址并设置地址
Address address = new Address();
address.setAddress("云南大理");
//仅为1端实体(消费者)设置它所对应的N端实体(地址)内容
customer.getAddressSet().add(address);//设置消费者所对应的地址
//仅持久化1端实体(消费者实体)即可
session.save(customer);
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
if(sessionFactory!=null){
sessionFactory.close();
}
}
}
第二种方法确实是简单的写法,需要设置属性,示例的代码属性都比较少,给人感觉两种方法的代码量相差不大,错觉,错觉…
##2.级联删除操作
级联删除的时候,同样需要进入1端(消费者实体)的set标签设置属性cascade=“delete”,这样在删除一个消费者的时候,会自动删除该消费者的所有地址信息。cascade属性可以同时设置多个值,以同时具备级联删除级联插入的功能:
cascade=“delete, save-update”。而下面的级联删除操作其实与之前的常规CRUD中的删除是完全一样的,不过是我们配置了cascade属性,删除的具体过程:
会先查询被删除信息A, 然后根据外键查询与A相关的信息B,然后将B的外键设置为null,再删除B,最后删除A
@Test
public void test(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.getCurrentSession();
transaction = session.getTransaction();
transaction.begin();
//获取要删除的对象
Customer customer = (Customer) session.get(Customer.class, 2);
//直接删除该对象,与之相关的地址也会被删除
session.delete(customer);
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
if(sessionFactory!=null){
sessionFactory.close();
}
}
}
##3.级联修改操作
下面演示了如何将id=2的用户地址转移给id=1的用户,首先还是先获取被转移的地址,以及所转移给的用户,然后将这两者建立关系,因为是持久态对象,所以也不用主动进行save()操作。
但是观察控制台输出的执行语句会发现,Hibernate对外键的设置执行了两次,访问两次的原因是因为Hibernate是双向维护外键的,也就是说1段以及N端都是有外键的,所以会分别修改一次,这就出现了性能问题,但是很显然我们只是在N端设置了外键,而1端其实并没有设置。所以**可以设置将1端放弃维护外键,**具体方式是在1端的set标签里面设置inverse属性,该属性的默认值为false表示不放弃关系的维护,将其置为true就可以。这样的话再次删除的时候,对主键的修改仅修改一次。
@Test
public void test(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.getCurrentSession();
transaction = session.getTransaction();
transaction.begin();
// id=2的地址原本是属于id=2的用户的,下面的代码将id=2的地址转移给id=1的用户,来演示级联修改操作
//获取地址
Address address = (Address) session.get(Address.class, 2);
//获取消费者
Customer customer = (Customer) session.get(Customer.class, 1);
address.setCustomer(customer);
customer.getAddressSet().add(address);
//上面的对象都是持久态对象,所以对他们的更改可以不用save(),在下面提交的时候,会自动进行修改,属于Hibernate一级缓存的特性
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
if(sessionFactory!=null){
sessionFactory.close();
}
}
}