1.一对多
customer
linkmen
客户对应多个联系人
一个联系人对应一个用户
1.customer.java
package it.cast.hema.hibernate;
import java.util.HashSet;
import java.util.Set;
public class Customer {
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_linkman;
private String cust_phone;
private String cust_mobile;
//使用set集合,表示一对多关系
private Set<LinkMan> linkMens = new HashSet<LinkMan>();
set/get方法
}
linkman.java
public class LinkMan {
private Long lkm_id;
private Character lkm_gender;
private String lkm_name;
private String lkm_phone;
private String lkm_email;
private String lkm_qq;
private String lkm_mobile;
private String lkm_memo;
private String lkm_position;
//表达多对一关系
private Customer customer ;
}
2.配置customer.xml文件
<hibernate-mapping package="it.cast.hema.hibernate">
<class name="Customer" table="tb_customer">
<id name="cust_id">
<generator class="native"></generator>
</id>
<property name="cust_name" column="cust_name"/>
<property name="cust_source" column="cust_source"/>
<property name="cust_industry" column="cust_industry"/>
<property name="cust_level" column="cust_level"/>
<property name="cust_linkman" column="cust_linkman"/>
<property name="cust_phone" column="cust_phone"/>
<property name="cust_mobile" column="cust_mobile"/>
<!--集合的配置-->
<!--
name:集合的属性名字
column:关联的外键
class:关联的实体表
cascade:级联操作
save-update:级联保存及更新
detele:级联删除
inverse:关系维护,优化性能
ture:表示放弃维护
false:默认值
一对多时,只能是一的一方有权放弃,而多的一方无权放弃
-->
<set name="linkMens" cascade="save-update" inverse="false">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"></one-to-many>
</set>
</class>
</hibernate-mapping>
配置linkmen.xml
<hibernate-mapping package="it.cast.hema.hibernate">
<class name="LinkMan" table="tb_linkman">
<id name="lkm_id">
<generator class="native"></generator>
</id>
<property name="lkm_gender" column="lkm_gender"/>
<property name="lkm_name" column="lkm_name"/>
<property name="lkm_phone" column="lkm_phone"/>
<property name="lkm_email" column="lkm_email"/>
<property name="lkm_qq" column="lkm_qq"/>
<property name="lkm_mobile" column="lkm_mobile"/>
<property name="lkm_memo" column="lkm_memo"/>
<property name="lkm_position" column="lkm_position"/>
<!--集合的配置-->
<!--
name:类的属性名字
column:关联的外键
class:关联的实体表类名
多对一
-->
<many-to-one name="customer" column="lkm_cust_id" class="Customer" cascade="save-update">
</many-to-one>
</class>
</hibernate-mapping>
还需在hibernate.cfg.xml添加映射文件
当中注意的是:一对多配置里面的set标签
这个只是起到外键作用,没有任何业务需求,同理多对一也一样
操作:
public class Demo {
@Test
public void fun(){
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction tra = session.beginTransaction();
Customer customer= new Customer();
customer.setCust_name("创智");
LinkMan linkman= new LinkMan();
LinkMan linkman1= new LinkMan();
linkman.setLkm_name("zhangsan");
linkman1.setLkm_name("wangwu");
//一对多
customer.getLinkMens().add(linkman);
customer.getLinkMens().add(linkman1);
//多对一
linkman.setCustomer(customer);
linkman1.setCustomer(customer);
session.save(customer);
session.save(linkman1);
session.save(linkman);
//提交
tra.commit();
}
//测试级联下的save-update
@Test
public void fun2(){
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction tra = session.beginTransaction();
Customer customer= new Customer();
customer.setCust_name("梦想科技");
LinkMan linkman= new LinkMan();
LinkMan linkman1= new LinkMan();
linkman.setLkm_name("wabgfei");
linkman1.setLkm_name("haha");
//一对多
customer.getLinkMens().add(linkman);
customer.getLinkMens().add(linkman1);
//多对一
linkman.setCustomer(customer);
linkman1.setCustomer(customer);
//保存 级联下的save-update
session.save(customer);
session.save(linkman1);
session.save(linkman);
//提交
tra.commit();
}
//测试级联下的删除 删除客户,级联删除联系人
@Test
public void fun3(){
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction tra = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class,3l);
//级联删除
session.delete(customer);
//提交
tra.commit();
}
@Test
//级联操作/保存联系人就会级联保存客户save-update
public void fun4(){
Session session = HibernateUtils.getCurrentSession();
//开启事务
Transaction tra = session.beginTransaction();
Customer customer= new Customer();
customer.setCust_name("科技");
LinkMan linkman = new LinkMan();
linkman.setLkm_name("wangfei");
//一对多
customer.getLinkMens().add(linkman);
//多对一
linkman.setCustomer(customer);
//级联保存 //保存客户就会跟着保存联系人
// session.save(customer);
//级联保存 //保存联系人就会跟着保存客户
session.save(linkman);
//提交
tra.commit();
// 为什么要使用级联操作就是为了简化几行代码,但是不建议使用那啥就是delete
}
}
3.多对多
关系表达:
对象中的表达
public class Role {
private Long role_id;
private String name;
//多对多使用set集合表示
private Set<User> users = new HashSet<User>();
}
public class User {
private Long user_id;
private String name;
private Set<Role> roles = new HashSet<Role>();
}
配置role.xml文件
```java
<hibernate-mapping package="it.hema.hebinate.manyandmany">
<class name="Role" table="tb_role">
<id name="role_id">
<generator class="native"></generator>
</id>
<property name="name" column="name"/>
<!--集合配置多对多`
name:集合属性名称
table:配置中间表名
key:
column:别人引用我的外键名称
class:类名
many-to-many:
Class:我与那个类有关系
column:我引用别人的外键名称
inverse:放弃维护
在多对多查询当中,一定要放弃要有一方放弃维护资格
-->
<set name="users" table="tb_role_user" inverse="true">
<key column="role_id"></key>
<many-to-many class="User" column="user_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
user.xml
<hibernate-mapping package="it.hema.hebinate.manyandmany">
<class name="User" table="tb_user">
<id name="user_id">
<generator class="native"></generator>
</id>
<property name="name" column="name"/>
<!--集合配置多对多
name:集合属性名称
table:配置中间表名
key:
column:别人引用我的外键名称(相当于我的主键)
class:类名
many-to-many:
Class:我与那个类有关系
column:我引用别人的外键名称 (相当于别人的主键)
-->
<set name="roles" table="tb_role_user" inverse="false">
<key column="user_id"></key>
<many-to-many class="Role" column="role_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
操作:
public class Demo {
@Test
public void fun() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Role role = new Role();
role.setName("清洁");
Role role1 = new Role();
role.setName("总裁");
User user = new User();
user.setName("wangfeifei");
// 多对多
user.getRoles().add(role1);// wangfeifei即使总裁又是清洁工
user.getRoles().add(role);
session.save(user);
session.save(role);
session.save(role1);
// org.hibernate.exception.ConstraintViolationException:
// Could not execute JDBC batch update
// Caused by: java.sql.BatchUpdateException: Duplicate entry '9-8' for
// key 'PRIMARY'
// at com.mysql.jdbc.PreparedStatement.executeBatchSerially
// 导致此异常的原因是因为:2张表保存时会同时维护各自的业务,这会涉及到对方表,所以会导致主键重复冲突
// 解决方法是在任意一张表当中的set键配置inverse="ture"放弃维护
tx.commit();
}
// 为用户增添一个角色
@Test
public void fun3() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//添加一个角色
Role role = new Role();
role.setName("保洁");
//获取用户
User user= (User)session.get(User.class, 21l);
user.getRoles().add(role);
//保存
session.save(user);
session.save(role);
//提交事务
tx.commit();
}
//为用户删除角色
@Test
public void fun4(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//获取用户
User user = (User) session.get(User.class,21L);
//获取角色
Role role =(Role) session.get(Role.class,32L);
// 删除用户角色
user.getRoles().remove(role);
//保存
session.save(user);
//提交事务
tx.commit();
}
}
总结:无论是多对一还是多对多都会有外键的存在,不同的是一对多会重新创建一个没有业务的外键来进行关联,而多对多则会采取中间表的形式来关联,也就是提取2个表的主键来进行创建中间表
set里面的集合 key里面是自己的主键,多对多里面则是关联的表和词表的主键 多对多里面还需注意的是,必须要有一方放弃维护,不然就会出现主键重复的问题