Hibernate 表操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate 表操作相关的知识,希望对你有一定的参考价值。

表与表之间关系回顾
  1. 一对多
    (1) 分类和商品关系
    (2) 客户和联系人

  2. 多对多
    (1) 订单和商品
    (2) 用户和角色

  3. 一对一

Hibernate一对多操作
级联:同时对多个表的数据进行操作
  1. 一对多映射操作(one to many)
  以客户与联系人为例
    (1) 实体类创建:
One:Customer(客户实体类):关键点在于存储联系人实例的集合属性(Set),它用于存储对应每一个联系人的对象

技术分享
 1 /**
 2  * 关键点:在于存储LinkMan的Set集合属性,用于存储联系人对象的集合
 3  */
 4 
 5 import java.util.HashSet;
 6 import java.util.Set;
 7 
 8 public class Customer {
 9     // 客户ID
10     private Integer cId;
11     
12     // 客户名称
13     private String custName;
14     
15     // 客户级别
16     private String custLevel;
17     
18     // 客户来源
19     private String custSource;
20     
21     // 联系电话
22     private String custPhone;
23     
24     // 手机
25     private String custMobile;
26 
27     // 联系人:在客户实体类里面表示多个联系人,实体类其中一个属性存储多个联系人。
28     private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();
29 
30     // 无参构造函数
31     public Customer() {
32     }
33 
34     public Integer getcId() {
35         return cId;
36     }
37 
38     public void setcId(Integer cId) {
39         this.cId = cId;
40     }
41 
42     public String getCustName() {
43         return custName;
44     }
45 
46     public void setCustName(String custName) {
47         this.custName = custName;
48     }
49 
50     public String getCustLevel() {
51         return custLevel;
52     }
53 
54     public void setCustLevel(String custLevel) {
55         this.custLevel = custLevel;
56     }
57 
58     public String getCustSource() {
59         return custSource;
60     }
61 
62     public void setCustSource(String custSource) {
63         this.custSource = custSource;
64     }
65 
66     public String getCustPhone() {
67         return custPhone;
68     }
69 
70     public void setCustPhone(String custPhone) {
71         this.custPhone = custPhone;
72     }
73 
74     public String getCustMobile() {
75         return custMobile;
76     }
77 
78     public void setCustMobile(String custMobile) {
79         this.custMobile = custMobile;
80     }
81 
82     public Set<LinkMan> getSetLinkMan() {
83         return setLinkMan;
84     }
85 
86 }
Customer Entity Code

Many:LinkMan(联系人实体类):关键点在于存储客户实例的Customer的属性,它用于存储对应的客户对象。

技术分享
 1 /**
 2  * 关键点:在于Customer属性,它用于存储对应的客户对象。
 3  */
 4 
 5 public class LinkMan {
 6     // 联系人ID
 7     private Integer lkmId;
 8 
 9     // 联系人姓名
10     private String lkmName;
11 
12     // 联系人性别
13     private String lkmGender;
14 
15     // 联系人办公电话
16     private String lkmPhone;
17 
18     // 在联系人实体类里面表示所属客户,一个联系人只能有一个客户
19     // 存储对应的客户对象
20     private Customer customer;
21 
22     public LinkMan() {
23     }
24 
25     public Integer getLkmId() {
26         return lkmId;
27     }
28 
29     public void setLkmId(Integer lkmId) {
30         this.lkmId = lkmId;
31     }
32 
33     public String getLkmName() {
34         return lkmName;
35     }
36 
37     public void setLkmName(String lkmName) {
38         this.lkmName = lkmName;
39     }
40 
41     public String getLkmGender() {
42         return lkmGender;
43     }
44 
45     public void setLkmGender(String lkmGender) {
46         this.lkmGender = lkmGender;
47     }
48 
49     public String getLkmPhone() {
50         return lkmPhone;
51     }
52 
53     public void setLkmPhone(String lkmPhone) {
54         this.lkmPhone = lkmPhone;
55     }
56 
57     public Customer getCustomer() {
58         return customer;
59     }
60 
61     public void setCustomer(Customer customer) {
62         this.customer = customer;
63     }
64 
65 }
LinkMan Entity Code

    (2) 映射文件配置:

Customer.hbm.xml:关键点在于set标签中配置Many(多方)信息

技术分享
 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <!-- Generated 2017-10-1 0:18:54 by Hibernate Tools 3.5.0.Final -->
 5 <hibernate-mapping>
 6     <class name="code.entity.Customer" table="CUSTOMER">
 7         <id name="cId" type="java.lang.Integer">
 8             <column name="CID" />
 9             <generator class="native" />
10         </id>
11         <property name="custName" type="java.lang.String">
12             <column name="CUSTNAME" />
13         </property>
14         <property name="custLevel" type="java.lang.String">
15             <column name="CUSTLEVEL" />
16         </property>
17         <property name="custSource" type="java.lang.String">
18             <column name="CUSTSOURCE" />
19         </property>
20         <property name="custPhone" type="java.lang.String">
21             <column name="CUSTPHONE" />
22         </property>
23         <property name="custMobile" type="java.lang.String">
24             <column name="CUSTMOBILE" />
25         </property>
26         <!-- 在客户映射文件中,表示所有联系人 
27               使用set标签标识所有联系人 
28              set标签里面有name属性:
29                    客户实体类里面表示联系人的set集合的属性名称 
30              cascade:
31                  级联配置,表示下级对象(LinkMan的对象会自动关联且保存)
32              inverse:
33                  默认为false:表示不放弃外键关系维护
34                        true:表示放弃外键关系维护
35         -->
36         <set name="setLinkMan" table="LINKMAN" cascade="save-update,delete" inverse="false">
37             <!-- key:指外键 
38                  column:对应外键名称
39                  hibernate机制:双向维护外键在One和Many都要配置外键
40             -->
41             <key>
42                 <column name="CLID" />
43             </key>
44             <!-- 配置实体类One和Many的关系
45                  one-to-many:指定Many(多方)的class
46                  class:Many(多方)实体类的全路径
47             -->
48             <one-to-many class="code.entity.LinkMan" />
49         </set>
50     </class>
51 </hibernate-mapping>
Customer.hbm.xml

LinkMan.hbm.xml:

技术分享
 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <!-- Generated 2017-10-1 0:18:54 by Hibernate Tools 3.5.0.Final -->
 5 <hibernate-mapping>
 6     <class name="code.entity.LinkMan" table="LINKMAN">
 7         <id name="lkmId" type="java.lang.Integer">
 8             <column name="LKMID" />
 9             <generator class="native" />
10         </id>
11         <property name="lkmName" type="java.lang.String">
12             <column name="LKMNAME" />
13         </property>
14         <property name="lkmGender" type="java.lang.String">
15             <column name="LKMGENDER" />
16         </property>
17         <property name="lkmPhone" type="java.lang.String">
18             <column name="LKMPHONE" />
19         </property>
20         
21         <!-- 表示联系人所属客户
22              name:存储Customer对象属性的属性名(customer)
23              class:指向Customer实体类的全路径
24              column:外键名称[创建数据表字段名称](跟One[一方]配置的key值一致)
25          -->
26         <many-to-one name="customer" class="code.entity.Customer"
27             fetch="join">
28             <column name="CID" />
29         </many-to-one>
30     </class>
31 </hibernate-mapping>
LinkMan.hbm.xml

  2. 一对多级联保存(在One[一方]的映射文件配置cascade属性 = "save-update")

技术分享
 1 package code.test;
 2 
 3 import org.hibernate.Session;
 4 import org.hibernate.SessionFactory;
 5 import org.hibernate.Transaction;
 6 import org.junit.Test;
 7 
 8 import code.entity.Customer;
 9 import code.entity.LinkMan;
10 import code.utils.HibernateUtil;
11 
12 public class TestCode {
13     @Test
14     public void testSave() {
15         // Hibernate版本 5.2.11
16         SessionFactory sf = HibernateUtil.getSessionFactory();// 获取SessionFactory
17         Session session = sf.openSession();// 打开session
18         Transaction transaction = session.beginTransaction();// 开启事务
19 
20         // 创建客户对象
21         Customer c = new Customer();
22         c.setCustName("CNAME");
23         c.setCustLevel("vip");
24         c.setCustMobile("020123123");
25         c.setCustPhone("123123");
26         c.setCustSource("source");
27 
28         // 创建联系人
29 
30         LinkMan l = new LinkMan();
31         l.setLkmName("kname");
32         l.setLkmGender("测试");
33         l.setLkmPhone("123123");
34 
35         // 将客户对象保存到联系人的客户属性成员中
36         // 当在Customer.hbm.xml中的set标签中配置了cascade="save-update"后,盖面这行代码便可不用操作
37         // l.setCustomer(c);
38 
39         // 客户对象set属性,用于保存联系人对象信息
40         // 将联系人添加至客户对象的set集合属性成员中
41         c.getSetLinkMan().add(l);
42 
43         // 保存对象
44         session.save(c);
45         session.save(l);
46 
47         // 提交事务
48         transaction.commit();
49 
50         // 关闭资源
51         session.close();
52         sf.close();
53     }
54 }
级联操作 - "保存"代码演示

  3. 一对多级联删除(在One[一方]的映射文件配置cascade属性 = "delete")

技术分享
 1     @Test
 2     public void testDelete() {
 3         // Hibernate版本 5.2.11
 4         SessionFactory sf = HibernateUtil.getSessionFactory();// 获取SessionFactory
 5         Session session = sf.openSession();// 打开session
 6         Transaction transaction = session.beginTransaction();// 开启事务
 7         Customer customer = session.get(Customer.class, 1);
 8         session.delete(customer);
 9         
10         // 执行事务
11         transaction.commit();
12 
13         // 关闭资源
14         session.close();
15         sf.close();
16     }
级联操作 - "删除"代码演示

  4. 一对多级联更新

技术分享级联操作 - 
 1     @Test
 2     public void testUpdate() {
 3         // Hibernate版本 5.2.11
 4         SessionFactory sf = HibernateUtil.getSessionFactory();// 获取SessionFactory
 5         Session session = sf.openSession();// 打开session
 6         Transaction transaction = session.beginTransaction();// 开启事务
 7 
 8         // 获取客户对象
 9         Customer customer = session.get(Customer.class, 1);
10         // 获取联系人对象
11         LinkMan lm = session.get(LinkMan.class, 3);
12 
13         // 将linkman对象添加到customer的set集合属性中
14         customer.getSetLinkMan().add(lm);
15         
16         //LinkMan保存customer
17         lm.setCustomer(customer);
18         
19         // 更新
20         // session.update(customer);
21 
22         // 提交事务
23         transaction.commit();
24 
25         // 关闭资源
26         session.close();
27         sf.close();
28     }
"更新"代码演示

  5. inverse属性
    因为hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改客户时修改一次外键,修改联系人时也修改了一次外键,共修改了两次,造成效率问题。
    让一方不维护外键,在One(一方)的映射文件中set标签上使用inverse属性。

Hibernate多对多操作(多对多建表操作中,实体类之间存在着第三张表,用于间接联系数据之间的关系

  以用户和角色为例
  1. 创建理由互相表示关系的实体类

技术分享
 1 /**
 2  * 实体类:User创建
 3  */
 4 import java.util.HashSet;
 5 import java.util.Set;
 6 
 7 public class User {
 8     private Integer userId;// 用户ID
 9     private String userName;// 用户名称
10     private String userPassword;// 用户密码
11     private Set<Role> roleSet = new HashSet<Role>();
12 
13     public User() {
14     }
15 
16     public User(String userName, String userPassword) {
17         super();
18         this.userName = userName;
19         this.userPassword = userPassword;
20     }
21 
22     public Integer getUserId() {
23         return userId;
24     }
25 
26     public void setUserId(Integer userId) {
27         this.userId = userId;
28     }
29 
30     public String getUserName() {
31         return userName;
32     }
33 
34     public void setUserName(String userName) {
35         this.userName = userName;
36     }
37 
38     public String getUserPassword() {
39         return userPassword;
40     }
41 
42     public void setUserPassword(String userPassword) {
43         this.userPassword = userPassword;
44     }
45 
46     public Set<Role> getRoleSet() {
47         return roleSet;
48     }
49 
50     public void setRoleSet(Set<Role> roleSet) {
51         this.roleSet = roleSet;
52     }
53 
54 }
User Code
技术分享
 1 /**
 2  * 实体类:Role创建
 3  */
 4 
 5 import java.util.HashSet;
 6 import java.util.Set;
 7 
 8 public class Role {
 9     private Integer roleId;// 角色ID
10     private String roleName;// 角色名称
11     private String roleMemo;// 角色描述
12     private Set<User> userSet = new HashSet<User>();;
13 
14     public Role() {
15     }
16 
17     public Role(String roleName, String roleMemo) {
18         super();
19         this.roleName = roleName;
20         this.roleMemo = roleMemo;
21     }
22 
23     public Integer getRoleId() {
24         return roleId;
25     }
26 
27     public void setRoleId(Integer roleId) {
28         this.roleId = roleId;
29     }
30 
31     public String getRoleName() {
32         return roleName;
33     }
34 
35     public void setRoleName(String roleName) {
36         this.roleName = roleName;
37     }
38 
39     public String getRoleMemo() {
40         return roleMemo;
41     }
42 
43     public void setRoleMemo(String roleMemo) {
44         this.roleMemo = roleMemo;
45     }
46 
47     public Set<User> getUserSet() {
48         return userSet;
49     }
50 
51     public void setUserSet(Set<User> userSet) {
52         this.userSet = userSet;
53     }
54 
55 }
Role Code

  2. 多对多映射关系配置(在映射文件中使用set标签进行配置)

技术分享

技术分享
 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <class name="code.entity.User" table="USER">
 6         <id name="userId" type="java.lang.Integer">
 7             <column name="USERID" />
 8             <generator class="native" />
 9         </id>
10         <property name="userName" type="java.lang.String">
11             <column name="USERNAME" />
12         </property>
13         <property name="userPassword" type="java.lang.String">
14             <column name="USERPASSWORD" />
15         </property>
16         
17         <!-- 
18             表示所有的Role
19                 name属性:角色的set集合名称
20                 table属性:第三张表名称
21                 cascade属性:哪些执行语句会启用级联操作
22                         save-update:保存/更新时启用级联操作
23                         delete:删除时启用级联操作
24         -->
25         <set name="roleSet" table="USER_ROLE" cascade="save-update,dalete" inverse="false" lazy="true">
26         <!-- KEY标签里面配置
27                 配置当前映射文件在第三张表的字段名称
28         -->
29             <key>
30                 <column name="USERID" />
31             </key>
32             <!-- class:多对多映射的实体类全路径
33                 column:该实体类在第三张表的外键名称
34             -->
35             <many-to-many class="code.entity.Role" column="ROLEID"/>
36         </set>
37     </class>
38 </hibernate-mapping>
User.hbm.xml
技术分享
 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <class name="code.entity.Role" table="ROLE">
 6         <id name="roleId" type="java.lang.Integer">
 7             <column name="ROLEID" />
 8             <generator class="assigned" />
 9         </id>
10         <property name="roleName" type="java.lang.String">
11             <column name="ROLENAME" />
12         </property>
13         <property name="roleMemo" type="java.lang.String">
14             <column name="ROLEMEMO" />
15         </property>
16         
17         <!-- 
18             表示所有的Role
19                 name属性:角色的set集合名称
20                 table属性:第三张表名称
21         -->
22         <set name="userSet" table="USER_ROLE" cascade="save-update" inverse="false" lazy="true">
23          <!-- KEY标签里面配置
24                 配置当前映射文件在第三张表的字段名称
25         -->
26             <key>
27                 <column name="ROLEID" />
28             </key>
29              <!-- class:多对多映射的实体类全路径
30                 column:该实体类在第三张表的外键名称
31             -->
32             <many-to-many class="code.entity.User" column="USERID"/>
33         </set>
34     </class>
35 </hibernate-mapping>
Role.hbm.xml

  3. 多对多级联保存

技术分享
 1 /*
 2  * 多对多 - 级联保存演示
 3  */
 4 
 5 import org.hibernate.Session;
 6 import org.hibernate.SessionFactory;
 7 import org.hibernate.Transaction;
 8 import org.junit.Test;
 9 
10 import code.entity.Role;
11 import code.entity.User;
12 import code.utils.HibernateUtil;
13 
14 public class TestCode {
15     @Test
16     public void testSave() {
17         // Hibernate版本 5.2.11
18         SessionFactory sf = HibernateUtil.getSessionFactory();// 获取SessionFactory
19         Session session = sf.openSession();// 打开session
20         Transaction transaction = session.beginTransaction();// 开启事务
21 
22         // 创建用户(2个)
23         User user1 = new User("一号用户", "123");
24         User user2 = new User("二号用户", "456");
25 
26         // 创建角色(3个)
27         Role role1 = new Role("角色一号", "一号");
28         Role role2 = new Role("角色二号", "二号");
29         Role role3 = new Role("角色三号", "三号");
30 
31         // 给用户添加角色
32         user1.getRoleSet().add(role1);
33         user1.getRoleSet().add(role2);
34 
35         user2.getRoleSet().add(role2);
36         user2.getRoleSet().add(role3);
37 
38         // 保存用户对象
39         session.save(user1);
40         session.save(user2);
41 
42         // 执行事务
43         transaction.commit();
44 
45         // 关闭资源
46         session.close();
47         sf.close();
48     }
49 }
ManyToMany Demo Code

  4. 维护第三张表

    1) 用户和角色多对多关系,维护关系通过第三张表维护,该表间接体现了用户与角色之间的关系

    2) 让某个用户有某个角色(增加角色关系)

      - 获取/新建用户对象;获取/新建角色对象

      - 将角色对象放到用户的set集合属性中

技术分享
 1 public class TestCode {
 2     @Test
 3     public void testAddRoleIntoUser() {
 4         // Hibernate版本 5.2.11
 5         SessionFactory sf = HibernateUtil.getSessionFactory();// 获取SessionFactory
 6         Session session = sf.openSession();// 打开session
 7         Transaction transaction = session.beginTransaction();// 开启事务
 8 
 9         // 获取用户对象
10         User user = session.get(User.class, 1);
11 
12         // 获取角色对象
13         Role role = session.get(Role.class, 3);
14 
15         // 获取set集合属性,并添加角色
16         user.getRoleSet().add(role);
17 
18         // 执行事务
19         transaction.commit();
20 
21         // 关闭资源
22         session.close();
23         sf.close();
24     }
25 }
AddRoleIntoUser

    3) 让某个用户没有某个角色(移除角色关系)

      - 根据ID查询用户

      - 获取用户对象的set集合属性,调用remove方法将角色对象从set集合中移除

技术分享
 1 public class TestCode {
 2     @Test
 3     public void testRemoveRoleOutUser() {
 4         // Hibernate版本 5.2.11
 5         SessionFactory sf = HibernateUtil.getSessionFactory();// 获取SessionFactory
 6         Session session = sf.openSession();// 打开session
 7         Transaction transaction = session.beginTransaction();// 开启事务
 8 
 9         // 获取用户对象
10         User user = session.get(User.class, 2);
11         
12         // 获取角色对象
13         Role role = session.get(Role.class, 3);
14 
15         user.getRoleSet().remove(role);
16 
17         // 执行事务
18         transaction.commit();
19 
20         // 关闭资源
21         session.close();
22         sf.close();
23     }
24 }
RemoveRoleOutUser













以上是关于Hibernate 表操作的主要内容,如果未能解决你的问题,请参考以下文章

具有运行时 pojos 的带有 Hibernate 的 OSGi 片段包

Hibernate5.x表与表之间的关系操作代码实现

Hibernate + MySQL:如何为数据库和表设置编码 utf-8

Hibernate 表操作

Hibernate基础

Hibernate 自动生产表