Java之hibernate表间关系
程序员文章站
2022-07-12 21:20:48
...
一对多
Customer实体类
表示一对多关系的容器:
// 容器必须初始化才能保存东西
private Set<LinkMan> linkMans = new HashSet<>();
LinkMan实体类
// 使用一的对象来表示表与表之间的关系
private Customer customer;
Customer.hbm.xml
<hibernate-mapping package="com.lanou3g.bean">
<class name="Customer" table="cst_customer">
<id name="cust_id" column="cust_id">
<generator class="native"></generator>
</id>
<property name="cust_name" column="cust_name" ></property>
<property name="cust_source" column="cust_source" ></property>
<property name="cust_industry" column="cust_industry" ></property>
<property name="cust_level" column="cust_level" ></property>
<property name="cust_linkman" column="cust_linkman" ></property>
<property name="cust_phone" column="cust_phone" ></property>
<property name="cust_mobile" column="cust_mobile" ></property>
<!-- 配置表关系的容器 -->
<!--
name:实体类中容器的属性名
column:表中的外键名
class:表示一对多中 多表的类(全类名)
inverse 控制是否维护外键关系
默认维护外键的关系 默认值false
结语 inverse 可以减少hibernate 无用操作 提高效率
cascade 级联操作 减少点代码
save-update
delete
all == save-update + delete
如果要用级联操作 就用save-update
请慎用delete
-->
<set name="linkMans" inverse="true">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"/>
</set>
</class>
</hibernate-mapping>
LinkMan.hbm.xml
<hibernate-mapping package="com.lanou3g.bean">
<class name="LinkMan" table="cst_linkman">
<id name="lkm_id" column="lkm_id">
<generator class="native"></generator>
</id>
<property name="lkm_name" column="lkm_name" ></property>
<property name="lkm_gender" column="lkm_gender" ></property>
<property name="lkm_phone" column="lkm_phone" ></property>
<property name="lkm_mobile" column="lkm_mobile" ></property>
<property name="lkm_email" column="lkm_email" ></property>
<property name="lkm_qq" column="lkm_qq" ></property>
<property name="lkm_position" column="lkm_position" ></property>
<property name="lkm_memo" column="lkm_memo" ></property>
<!-- 配置表关系 -->
<!--
name:表示关系的对象的属性名
column:表中的外键名
class:多对一关系中 对应的实体类名(全类名)
注意:外键的属性 不要重复配置
-->
<many-to-one name="customer" column="lkm_cust_id" class="Customer"></many-to-one>
</class>
</hibernate-mapping>
测试添加一个客户 两个联系人
@Test
public void fun1() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
// 创建客户
Customer customer = new Customer();
customer.setCust_name("lanou");
// 创建联系人
LinkMan linkMan1 = new LinkMan();
linkMan1.setLkm_name("wl");
LinkMan linkMan2 = new LinkMan();
linkMan2.setLkm_name("lck");
// 添加实体类中的关系
// 把联系人添加到集合中
customer.getLinkMans().add(linkMan1);
customer.getLinkMans().add(linkMan2);
// 给联系人设置客户
linkMan1.setCustomer(customer);
linkMan2.setCustomer(customer);
// 保存到数据库
session.save(customer);
session.save(linkMan1);
session.save(linkMan2);
transaction.commit();
session.close();
}
对hibernate执行的sql语句的优化
打印的插入语句 是linkman在维护自己的表
并且在插入的时候 已经插入了外键(外键已经有了)
打印的更新语句 是Customer来维护从而打印出来的
这里对外键的维护 两个表都维护一遍 造成了多余的sql语句操作
使用inverse控制是否维护外键关系
删除客户为1的id为2的联系人
@Test
public void fun2() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
// 获取id为1的客户
// 持久态 在事务提交的时候 如果该对象被修改了 那么修改的数据 会被同步到数据库中
Customer customer = session.get(Customer.class, 1l);
// 获取id为2的联系人
LinkMan linkMan = session.get(LinkMan.class, 2l);
// 处理实体类的关系
customer.getLinkMans().remove(linkMan);
linkMan.setCustomer(null);
// 从数据库中删除
session.delete(linkMan);
transaction.commit();
session.close();
}
为客户id为1 添加联系人
@Test
public void fun3() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
// 获取id为1的客户
Customer customer = session.get(Customer.class, 1l);
// 创建联系人
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("zs");
// 处理实体类的关系
customer.getLinkMans().add(linkMan);
linkMan.setCustomer(customer);
// 保存到数据库
session.save(linkMan);
transaction.commit();
session.close();
}
测试级联操作(可以让你减少几行代码的工作量)
save-update:
public void fun4() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("JD");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("lsy");
customer.getLinkMans().add(linkMan);
//linkMan.setCustomer(customer);
session.save(customer);
//session.save(linkMan);
transaction.commit();
session.close();
}
delete:
@Test
public void fun5() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 1l);
session.delete(customer);
transaction.commit();
session.close();
}
多对多
User实体类
// 表示多对多关系
private Set<Role> roles = new HashSet<>();
Role实体类
// 表示多对多关系
private Set<User> users = new HashSet<>();
User.hbm.xml
<hibernate-mapping package="com.lanou3g.bean">
<class name="User" table="sys_user">
<id name="user_id" column="user_id">
<generator class="native"></generator>
</id>
<property name="user_code" column="user_code" ></property>
<property name="user_name" column="user_name" ></property>
<property name="user_password" column="user_password" ></property>
<property name="user_state" column="user_state" ></property>
<!-- 表示多对多关系 -->
<!--
name:对应容器的名
table:中间表的名字
column:被引用的外键
*****************
class:与之对应的表的类名(全类名)
column: 前面class中被引用的外键
-->
<set name="roles" table="sys_user_role" inverse="true">
<key column="user_id"></key>
<many-to-many class="Role" column="role_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
Role.hbm.xml
<hibernate-mapping package="com.lanou3g.bean">
<class name="Role" table="sys_role">
<id name="role_id" column="role_id">
<generator class="native"></generator>
</id>
<property name="role_name" column="role_name" ></property>
<property name="role_memo" column="role_memo" ></property>
<set name="users" table="sys_user_role">
<key column="role_id"></key>
<many-to-many class="User" column="user_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
保存两个员工两个角色
@Test
public void fun1() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
User user1 = new User();
user1.setUser_name("sc");
User user2 = new User();
user2.setUser_name("kd");
Role role1 = new Role();
role1.setRole_name("保镖");
Role role2 = new Role();
role2.setRole_name("保姆");
user1.getRoles().add(role1);
user1.getRoles().add(role2);
user2.getRoles().add(role1);
user2.getRoles().add(role2);
role1.getUsers().add(user1);
role1.getUsers().add(user2);
role2.getUsers().add(user1);
role2.getUsers().add(user2);
session.save(user1);
session.save(user2);
session.save(role1);
session.save(role2);
transaction.commit();
session.close();
}
每个表默认都会维护自己的外键关系
中间表使用的联合主键 如果两张表都维护外键关系
也就是说 都会对中间表进行操作 这时会发生重复插入相同的外键值
注意:所以多对多操作必须要有一张表放弃对外键关系的维护
为id为1的员工增加一个角色
@Test
public void fun2() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
User user = session.get(User.class, 1l);
Role role = new Role();
role.setRole_name("保洁");
// 注意双侧关系都要添加上
user.getRoles().add(role);
role.getUsers().add(user);
session.save(role);
transaction.commit();
session.close();
}
为id为1的员工解除一个角色
@Test
public void fun3() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
User user = session.get(User.class, 1l);
Role role = session.get(Role.class, 2l);
user.getRoles().remove(role);
role.getUsers().remove(user);
session.save(user);
session.save(role);
transaction.commit();
session.close();
}