26.Hibernate-主键和映射.md

时间:2023-12-17 15:38:50

目录

1.复合主键映射

数据库表可以用复合主键映射。但是复合主键映射使用时候需要注意:在配置文件中,需要使用一个对象来表示复合主键

  • 单一主键
    <class name="Employee" table="employee">
<!-- 主键 注意和类成员和表列名称的一致对应 -->
<id name="empId" column="EmpId" >
<!-- 主键的生成策略:
1.identity 自增长(mysql,db2)
2.sequence 自增长(序列), oracle中自增长是以序列方法实现
3.native 自增长【会根据底层数据库自增长的方式选择identity或sequence】
如果是mysql数据库, 采用的自增长方式是identity
如果是oracle数据库, 使用sequence序列的方式实现自增长 4.increment 自增长(会有并发访问的问题,一般在服务器集群环境使用会存在问题。) 5.assigned 指定主键生成策略为手动指定主键的值
6.uuid 指定uuid随机生成的唯一的值
7.foreign (外键的方式, one-to-one讲)
-->
<generator class="native" /> </id>
<!-- 非主键,同样一一映射
name:类的属性名称
column:表的字段名称
length:设定字段的长度,默认为255
type:设定映射表的类型,如果不写匹配类对应属性的类型
java类型:必须带完整包名:java.lang.String
hibernate类型:全部都是小写 -->
<property name="empName" column="EmpName"></property>
<property name="workDate" column="WorkDate"></property>
</class>
  • 复合主键

a. 首先需要将数据库表对应的对象类中的复合主键,提取为一个对象。所以需要新建一个类,将这个类对象作为表对象的属性。

特别要注意的是这个复合主键类对象一定要实现序列化方法

package per.liyue.code.hibernatehello;
import java.io.Serializable;
public class CompositeKeys implements Serializable {
private String name = null;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
private int id = 0;
}

b. 将序列化的对象添加到表对应的类对象中

public class Employee {
private CompositeKeys keys;
private String empName;
private Date workDate;
...... }

c. 在配置文件中将符合主键配置

    <class name="Employee" table="employee">
<composite-id name="keys">
<key-property name="name" type="String"></key-property>
<key-property name="id" type="int"></key-property>
</composite-id> <!-- 非主键,同样一一映射
name:类的属性名称
column:表的字段名称
length:设定字段的长度,默认为255
type:设定映射表的类型,如果不写匹配类对应属性的类型
java类型:必须带完整包名:java.lang.String
hibernate类型:全部都是小写 -->
<property name="empName" column="EmpName"></property>
<property name="workDate" column="WorkDate"></property>
</class>

目录

2.集合映射

2.1Set集合

假若有如下的数据库表:

  • 那么对应的类对象应该是
package per.liyue.code.hibernatecollection;
import java.util.Set;
/*
* 带有集合的类
*/
public class User {
private int userId;
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Set<String> getUserEmail() {
return userEmail;
}
public void setUserEmail(Set<String> userEmail) {
this.userEmail = userEmail;
}
//一个Set集合,对应数据库中的表,这个表的外键是User表的主键
private Set<String> userEmail;
}
  • 配置映射文件:

    要注意的是Set集合的配置,对应的数据类型必须填写
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Nov 9, 2006 6:27:53 PM by Hibernate Tools 3.2.0.beta7 -->
<!-- package:类对象所在的包
auto-import:表面是自动导入包,如果设定为false,则需要在执行hql语句时候将包名写清楚:
Demo:在true时候可以写为session.createQuery("from Employee").list();
在false时候必须写为session.createQuery("from per.liyue.code.hibernatehello.Employee").list();
-->
<hibernate-mapping package="per.liyue.code.hibernatecollection" auto-import="true">
<!-- 类与表的对应
name:类名称
table:表名称 -->
<class name="User" table="user"> <!-- 主键 注意和类成员和表列名称的一致对应 -->
<id name="userId" column="UserId" >
<generator class="native" />
</id> <property name="userName" column="UserName"></property> <!-- Set集合配置:
set-name:要映射的Set集合类
set-table:要映射的Set表
key-column:指定集合表的外键,也就是User表的主键
element-type:集合表其他字段的类型,必须填写!!!
element-column:集合表其他自动的表列名称
-->
<set name="userEmail" table="UserEmail">
<key column="UserId"></key>
<element type="string" column="EmailAddress"></element>
</set> </class>
</hibernate-mapping>
  • 配置Hibernate配置文件:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="foo">
<!-- 数据库连接配置 -->
<!-- 连接类 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 连接数据库 -->
<property name="hibernate.connection.url">jdbc:mysql:///hi</property>
<!-- 连接用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 连接密码 -->
<property name="hibernate.connection.password">root</property>
<!-- 数据库方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 其他配置 -->
<property name="hibernate.show_sql"></property> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 加载所有的映射 -->
<mapping resource="per/liyue/code/hibernatehello/Employee.hbm.xml"/>
<mapping resource="per/liyue/code/hibernatecollection/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
  • 最后保存数据
package per.liyue.code.hibernatecollection;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class App {
private static SessionFactory sf;
static{
sf = new Configuration().configure().buildSessionFactory();
} @Test
public void setOperation(){
Session s = sf.openSession();
s.beginTransaction(); /*
* Set:保存带Set的集合
*/
User user = new User();
user.setUserId(2);
user.setUserName("李四");
Set<String> email = new HashSet<>();
email.add("a@a.com");
email.add("b@b.com");
user.setUserEmail(email); s.save(user); s.getTransaction().commit();
s.close();
sf.close(); }
}

2.2其他集合

其他集合大体上类似Set集合,但是具体有不同

  • list

    list在配置文件中需要指定一个索引,因为list是有序的!!!

  • map

    map中key和value都需要指定类型

Demo:

将上文中的例子修改

package per.liyue.code.hibernatecollection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/*
* 带有集合的类
*/
public class User {
private int userId;
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Set<String> getUserEmail() {
return userEmail;
}
public void setUserEmail(Set<String> userEmail) {
this.userEmail = userEmail;
}
//一个Set集合,对应数据库中的表,这个表的外键是User表的主键
private Set<String> userEmail; //一个List集合
private List<String> userPhoneNumber = new ArrayList<>();
public List<String> getUserPhoneNumber() {
return userPhoneNumber;
}
public void setUserPhoneNumber(List<String> userPhoneNumber) {
this.userPhoneNumber = userPhoneNumber;
} //一个Map集合
private Map<String, String> userAddress = new HashMap<>();
public Map<String, String> getUserAddress() {
return userAddress;
}
public void setUserAddress(Map<String, String> userAddress) {
this.userAddress = userAddress;
} }
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Nov 9, 2006 6:27:53 PM by Hibernate Tools 3.2.0.beta7 -->
<!-- package:类对象所在的包
auto-import:表面是自动导入包,如果设定为false,则需要在执行hql语句时候将包名写清楚:
Demo:在true时候可以写为session.createQuery("from Employee").list();
在false时候必须写为session.createQuery("from per.liyue.code.hibernatehello.Employee").list();
-->
<hibernate-mapping package="per.liyue.code.hibernatecollection" auto-import="true">
<!-- 类与表的对应
name:类名称
table:表名称 -->
<class name="User" table="user"> <!-- 主键 注意和类成员和表列名称的一致对应 -->
<id name="userId" column="user_id" >
<generator class="native" />
</id> <property name="userName" column="user_name"></property> <!-- Set集合配置:
set-name:要映射的Set集合类
set-table:要映射的Set表
key-column:指定集合表的外键,也就是User表的主键
element-type:集合表其他字段的类型
element-column:集合表其他自动的表列名称
-->
<set name="userEmail" table="UserEmail">
<key column="user_id"></key>
<element type="string" column="email_address"></element>
</set> <!-- List集合配置
list-index:需要为list指定排序,因为list是有序的
-->
<list name="userPhoneNumber" table="UserPhoneNumber">
<key column="user_id"></key>
<list-index column="list_index"></list-index>
<element type="string" column="phone_number"></element>
</list> <!-- Map集合配置 -->
<map name="userAddress">
<key column="user_id"></key>
<map-key type="string" column="area"></map-key>
<element type="string" column="address"></element>
</map> </class>
</hibernate-mapping>

最后再修改实现类

package per.liyue.code.hibernatecollection;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class App {
private static SessionFactory sf;
static{
sf = new Configuration().configure().buildSessionFactory();
} @Test
public void setOperation(){
Session s = sf.openSession();
s.beginTransaction(); /*
* Set:保存带Set的集合
*/
User user = new User();
user.setUserId(2);
user.setUserName("孙五");
Set<String> email = new HashSet<>();
email.add("c@a.com");
email.add("d@b.com");
user.setUserEmail(email); /*
* List:保存List
*/
user.getUserPhoneNumber().add("189898989");
user.getUserPhoneNumber().add("108080808"); /*
* Map:保存Map
*/
user.getUserAddress().put("上海", "浦东");
user.getUserAddress().put("杭州", "西湖"); s.save(user); s.getTransaction().commit();
s.close();
sf.close(); }
}

目录

3.集合数据的读取

集合数据的读取采用懒加载方式:当映射正确的时候,使用到相关集合数据,hibernate才会想数据库发送执行语句

Demo:

将上述例子中的App类中增加读取函数

@Test
public void GetCollection(){
Session s = sf.openSession();
s.beginTransaction(); User user = (User) s.get(User.class, 4);
System.out.println("查询到用户的信息:");
System.out.println("用户ID:" + user.getUserId());
System.out.println("用户名字:" + user.getUserName()); /*
* 懒加载:当有正确的映射时候,只有当使用集合相关数据时候,hibernate才会想数据库发送相关语句
*/
System.out.println("用户邮箱:" + user.getUserEmail());
System.out.println("用户电话: " + user.getUserPhoneNumber());
System.out.println("用户地址: " + user.getUserAddress()); s.getTransaction().commit();
s.close();
sf.close();
}

可以得到结果:

查询到用户的信息:

用户ID:4

用户名字:孙五

用户邮箱:[d@b.com, c@a.com]

用户电话: [189898989, 108080808]

用户地址: {上海=浦东, 杭州=西湖}


目录

4.一对多和多对一映射

4.1概念

实际开发中,有很多情况例如上面的主数据类中保存了子数据类的对象,当时常常这个集合对象内容不是单一的基本数据类型,需要用对象方式来保存更多的数据。这个时候就存在了一对多和多对一的映射关系

4.2配置和开发

4.2.1关键点

配置的关键在于对主数据类和子数据类都可以配置对应的配置文件:

  • 单向关联:配置一对多
  • 单向关联:配置多对一
  • 双向关联:配置上面两种单向关联均配置

    注意:配置了哪一种情况,就可以根据哪一种情况来操作数据。也就是说配置了一对多则可以通过一来维护多(保存时候保存一关联保存多),配置了多对一则可以通过多来维护一(保存时候保存多关联保存一)。因此在使用时候,为了提高效率,建议先保存一的一方再去保存多,因为反过来的话执行一次insert后还要多执行一次update,会降低执行效率!

4.2.2实例

  • 有数据关系:

  • 编写主数据类和子数据类:

package per.liyue.code.hibernate_multimapping;
import java.util.HashSet;
import java.util.Set;
/*
* 主数据类对象,包含了一个集合类型的属性,内容是另一个类的对象
*/
public class Department {
private int depId;
private String depName;
private Set<Employee> employee = new HashSet<Employee>();
public int getDepId() {
return depId;
}
public void setDepId(int depId) {
this.depId = depId;
}
public String getDepName() {
return depName;
}
public void setDepName(String depName) {
this.depName = depName;
}
public Set<Employee> getEmployee() {
return employee;
}
public void setEmployee(Set<Employee> employee) {
this.employee = employee;
}
}
package per.liyue.code.hibernate_multimapping;
/*
* 子数据类,这个类的对象是主数据类的集合元素
*/
public class Employee {
private int empId;
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
} private String empName;
public String getEmpName() {
return this.empName;
}
public void setEmpName(String empName) {
this.empName = empName;
} //多对一:
private Department dept;
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
} }
  • 配置两个类的配置文件
    • 一对多的配置
<!-- 主数据类的配置文件 -->
<set name="主数据类中的子数据类的类对象" table="子数据类的表名称">
<key column="主数据类的主键(也就是子数据类的外键)"></key>
<one-to-many class="子数据类的类名称,注意同一个包下可以不带包名称,注意不要在不同包下重复用一个类名称"/>
</set>
* 多对一的配置
<!-- 子数据类的配置文件 -->

<many-to-one name="子数据类中的主数据类对象" column="子数据类的外键(主数据类的主键)" class="主数据类名称"></many-to-one>  

  • Demo:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Nov 9, 2006 6:27:53 PM by Hibernate Tools 3.2.0.beta7 -->
<!-- package:类对象所在的包
auto-import:表面是自动导入包,如果设定为false,则需要在执行hql语句时候将包名写清楚:
Demo:在true时候可以写为session.createQuery("from Employee").list();
在false时候必须写为session.createQuery("from per.liyue.code.hibernatehello.Employee").list();
-->
<hibernate-mapping package="per.liyue.code.hibernate_multimapping" auto-import="true">
<class name="Department" table="Department">
<!-- 主键 -->
<id name="depId" column="dep_id" >
<generator class="native" />
</id> <property name="depName" column="dep_name"></property> <!-- 设置一对多关系:
name:集合中的类对象对应的类
table:集合中类对象对应的表
key:子数据类中对应外键
one-to-many:子数据类对应的类,如果是同一个包下的类可以不写包名
-->
<set name="employee" table="Employee">
<key column="dep_id"></key>
<one-to-many class="Employee"/>
</set> </class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Nov 9, 2006 6:27:53 PM by Hibernate Tools 3.2.0.beta7 -->
<!-- package:类对象所在的包
auto-import:表面是自动导入包,如果设定为false,则需要在执行hql语句时候将包名写清楚:
Demo:在true时候可以写为session.createQuery("from Employee").list();
在false时候必须写为session.createQuery("from per.liyue.code.hibernatehello.Employee").list();
-->
<hibernate-mapping package="per.liyue.code.hibernate_multimapping" auto-import="true">
<class name="Employee" table="Employee">
<!-- 主键 -->
<id name="empId" column="emp_id" >
<generator class="native" />
</id> <property name="empName" column="emp_name"></property> <!-- 设置多对一关系:
name:映射的主类对象
column:外键的字段名称
class:映射主类
-->
<many-to-one name="dept" column="dep_id" class="Department"></many-to-one> </class>
</hibernate-mapping>
  • 执行语句
package per.liyue.code.hibernate_multimapping;

import java.util.HashSet;
import java.util.Set; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test; public class App_Save {
private static SessionFactory sf;
static{
sf = new Configuration().configure().buildSessionFactory();
} @Test
/*
* 一维护多,无论保存时候先保存部门还是后保存部门,必须要多执行相应的update语句保证id一致。
*/
public void DemoOne2Many(){
Session s = sf.openSession();
s.beginTransaction(); Department dept = new Department();
dept.setDepName("硬件开发部"); Employee zhangSan = new Employee();
zhangSan.setEmpName("王五"); Employee liSi = new Employee();
liSi.setEmpName("赵二"); /*
*这里的映射关系是一对多,也就是通过部门来维护员工
*/
dept.getEmployee().add(zhangSan);
dept.getEmployee().add(liSi); s.save(zhangSan);
s.save(liSi);
s.save(dept); s.getTransaction().commit();
s.close();
sf.close(); } @Test
/*
* 推荐方式:通过多来维护一,这样高效!
*/
public void DemoMany2One(){
Session s = sf.openSession();
s.beginTransaction(); Department dept = new Department();
dept.setDepName("软件开发部"); Employee zhangSan = new Employee();
zhangSan.setEmpName("张三"); Employee liSi = new Employee();
liSi.setEmpName("李四"); /*
*这里的映射关系是多对一,也就是通过员工来维护部门
*/
zhangSan.setDept(dept);
liSi.setDept(dept); //这个时候如果部门保存在后面,则保存员工时候没有部门编号,会增加两条update语句
s.save(dept);
s.save(zhangSan);
s.save(liSi); s.getTransaction().commit();
s.close();
sf.close(); } }

执行的语句结果

一对多的情况:

Hibernate: insert into Employee (emp_name, dep_id) values (?, ?)

Hibernate: insert into Employee (emp_name, dep_id) values (?, ?)

Hibernate: insert into Department (dep_name) values (?)

Hibernate: update Employee set dep_id=? where emp_id=?

Hibernate: update Employee set dep_id=? where emp_id=?

多对一的情况:

Hibernate: insert into Department (dep_name) values (?)

Hibernate: insert into Employee (emp_name, dep_id) values (?, ?)

Hibernate: insert into Employee (emp_name, dep_id) values (?, ?)

在hibernate中唯一的方式把对象映射为外键的方式:many-to-one

建议通过多对一来维护,这样操作高效!

  • 读取数据
    • 懒加载:在执行的时候hibernate才发送并执行相关SQL语句
package per.liyue.code.hibernate_multimapping;

import java.util.HashSet;
import java.util.Set; import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test; public class App_Get {
private static SessionFactory sf;
static{
sf = new Configuration().configure().buildSessionFactory();
} @Test
/*
* 一对多和多对一的读取
*/
public void DemoOne2Many(){
Session s = sf.openSession();
s.beginTransaction(); Department dep = (Department)s.get(Department.class, 1);
System.out.println("从部门读取:" + dep.getDepId());
/*
* 懒加载:不执行下面的调用,hibernate不会向数据库发送相关语句并执行
*/
System.out.println("从部门读取:" + dep.getEmployee()); Employee emp = (Employee)s.get(Employee.class, 2);
System.out.println("从员工读取:" + emp.getEmpName());
System.out.println("从员工读取:" + emp.getDept()); s.getTransaction().commit();
s.close();
sf.close(); }
}

目录

5.反转:inverse

5.1概念

  • 表示反转控制,取消控制
  • 在一对多和多对一的关系中,一的一方可以设置inverse属性。

5.2实例

5.2.1配置

在上面的Department.hbm.xml中,在一对多的映射中可以设定:

<set name="employee" table="Employee" inverse="false">
<key column="dep_id"></key>
<one-to-many class="Employee"/>
</set>

这里的false是默认值,表示主数据类有控制权限,如果设置为true则表示没有控制权限

5.2.2影响

  • 保存:有影响,解除关联后,子数据类依旧会保存,但是外键关联取消,保存为NULL
  • 读取:无影响
  • 解除关联关系:有影响,解除关联关系的用法是先读取,然后主类调用clear()方法。如果解除,则则不能解除关系,但是不报错
  • 删除:有影响,解除后如果外键有值,删除会违反主外键约束而报错,如果外键没有值为NULL,则可以删除

目录

6.级联:cascade

6.1概念

级联操作的设置,在一对多和多对一均可配置。如在配置文件中:

<set name="employee" table="Employee" inverse="false" cascade="none">
<key column="dep_id"></key>
<one-to-many class="Employee"/>
</set>

6.2配置

只在一对多一方配置

级联操作有以下几种配置:

  • none:默认值,不级联操作
  • save-update:设置级联保存和更新。注意:save和update不能拆分使用
  • save-update,delete:设置级联保存、更新和删除
  • all: 全部

6.3inserse和cascade区别

不能在一起使用


目录

7.多对多映射

7.1关系

在实际应用中有多对多的映射关系:

不同的人有不同的角色,不同的角色对应多个人。在数据库中二者的关联关系通常放到另一个表中。形成了多对多映射

7.2配置和实现

7.2.1定义两个数据类

package per.liyue.code.hibernate_mu2mu;

import java.util.HashSet;
import java.util.Set;
/*
* 数据类角色
*/
public class Role {
private int roleId;
private String roleName; //包含另一个数据类对象
private Set<Person> person = new HashSet<>(); public int getRoleId() {
return roleId;
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public Set<Person> getPerson() {
return person;
}
public void setPerson(Set<Person> person) {
this.person = person;
}
}


7.2.2配置二者的映射关系

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Nov 9, 2006 6:27:53 PM by Hibernate Tools 3.2.0.beta7 -->
<!-- package:类对象所在的包
auto-import:表面是自动导入包,如果设定为false,则需要在执行hql语句时候将包名写清楚:
Demo:在true时候可以写为session.createQuery("from Employee").list();
在false时候必须写为session.createQuery("from per.liyue.code.hibernatehello.Employee").list();
-->
<hibernate-mapping package="per.liyue.code.hibernate_mu2mu" auto-import="true">
<class name="Role" table="Role">
<!-- 主键 -->
<id name="roleId" column="r_id" >
<generator class="native" />
</id> <property name="roleName" column="r_name"></property> <!-- 设置多对多关系:
name:
-->
<set name="person" table="Reletionship" inverse="false" cascade="none">
<key column="r_id"></key>
<many-to-many column="per_id" class="Person"></many-to-many>
</set> </class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- Generated Nov 9, 2006 6:27:53 PM by Hibernate Tools 3.2.0.beta7 -->
<!-- package:类对象所在的包
auto-import:表面是自动导入包,如果设定为false,则需要在执行hql语句时候将包名写清楚:
Demo:在true时候可以写为session.createQuery("from Employee").list();
在false时候必须写为session.createQuery("from per.liyue.code.hibernatehello.Employee").list();
-->
<hibernate-mapping package="per.liyue.code.hibernate_mu2mu" auto-import="true">
<class name="Person" table="Person">
<!-- 主键 -->
<id name="personId" column="per_id" >
<generator class="native" />
</id> <property name="personName" column="per_name"></property> <!-- 设置多对多关系:
name:另一个类对象的实例名称
talbe:二者关系的数据库映射表
key-column:当前类的主键,关系表的外键
many-to-mangy-column:另一个类的主键,关系表中的另一个外键
many-to-mangy-class:另一个类的类名称
-->
<set name="role" table="Reletionship" inverse="false" cascade="none" >
<key column="per_id"></key>
<many-to-many column="r_id" class="Role"></many-to-many>
</set> </class>
</hibernate-mapping>

7.2.3实现业务

package per.liyue.code.hibernate_mu2mu;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test; import per.liyue.code.hibernate_multimapping.Department;
import per.liyue.code.hibernate_multimapping.Employee; public class App {
private static SessionFactory sf;
static{
sf = new Configuration().configure().buildSessionFactory();
} @Test
/*
*
*/
public void DemoMany2Many(){
Session s = sf.openSession();
s.beginTransaction(); //创建
Person p_zhangsan = new Person();
p_zhangsan.setPersonName("张三");
Person p_lisi = new Person();
p_lisi.setPersonName("李四"); Role r_teacher = new Role();
r_teacher.setRoleName("教师");
Role r_student = new Role();
r_student.setRoleName("学生");
Role r_developer = new Role();
r_developer.setRoleName("开发"); //关系
p_zhangsan.getRole().add(r_teacher);
p_zhangsan.getRole().add(r_developer); p_lisi.getRole().add(r_student); //保存
s.save(p_zhangsan);
s.save(p_lisi);
s.save(r_teacher);
s.save(r_student);
s.save(r_developer); s.getTransaction().commit();
s.close();
sf.close(); }
}

8.映射关系配置总结

  • 一对多:

<set name="映射的集合属性" table="(可选)集合属性对应的外键表">
<key column="外键表的,外键字段" />
<one-to-many class="集合元素的类型" />
</set>
  • 多对一:

<many-to-one name="对象属性" class="对象类型" column="外键字段字段" />
  • 多对多

<set name="" table="">
<key column="" />
<many-to-many column="" class="">
</set>

目录

8.一对一映射

8.1分类

可以有两种一对一映射:

  • 基于外键,外键唯一
  • 基于主键

    假设有用户和身份证的一一映射,可以有下面的两种数据库表关系

那么两种模型下的实例为:

8.2有主键的映射

8.2.1类对象





8.2.2配置文件





8.2.3主配置和实现





8.3无主键的映射

8.3.1类对象





8.3.2配置文件





8.3.3主配置和实现






目录

9.组件映射

9.1适用范围

  • 组件映射指的是一个类中包含了另一个类的对象。是包含与被包含的概念
  • 映射会将两个类映射到一个表中

9.2实例

9.2.1类

package per.liyue.code.component_demo;/** * Created by liyue on 2016/10/21. */public class User{    private int id;    private String name;    private Wheel wheel;}```

```java
package per.liyue.code.component_demo;/** * Created by liyue on 2016/10/21. */public class Wheel{ private int count; public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } private int size;}``` ## 9.2.2配置文件
```xml
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><!-- Generated Nov 9, 2006 6:27:53 PM by Hibernate Tools 3.2.0.beta7 --><!-- package:类对象所在的包 auto-import:表面是自动导入包,如果设定为false,则需要在执行hql语句时候将包名写清楚: Demo:在true时候可以写为session.createQuery("from Employee").list(); 在false时候必须写为session.createQuery("from per.liyue.code.hibernatehello.Employee").list(); --><hibernate-mapping package="per.liyue.code.component_demo.User" auto-import="true"> <class name="User" table="t_User"> <!-- 主键 --> <id name="id" column="user_id" > <generator class="native" /> </id> <property name="name" column="user_name"></property> <!-- 组件关系 --> <component name="wheel"> <!--组件成员--> <property name="count"></property> <property name="size"></property> </component> </class></hibernate-mapping>``` ---
[toc]
--- # 10.继承映射
## 10.1概念
### 10.1.1简单继承
有多少个子类写多少个配置文件

// 动物类

public abstract class Animal {

private int id;
private String name;

<class name="Cat" table="t_Cat">
<!-- 简单继承映射: 父类属性直接写 -->
<id name="id">
<generator class="native"></generator>
</id>
<property name="na"></property>
<property name="catchMouse"></property>
</class>

@Test

public void getSave() {

	Session session = sf.openSession();
session.beginTransaction(); // 保存

// Cat cat = new Cat();

// cat.setName("大花猫");

// cat.setCatchMouse("抓小老鼠");

// session.save(cat);

	// 获取时候注意:当写hql查询的使用,通过父类查询必须写上类的全名
Query q = session.createQuery("from cn.itcast.e_extends1.Animal");
List<Animal> list = q.list();
System.out.println(list); session.getTransaction().commit();
session.close(); }


### 10.1.2复杂继承
* 多个子类共用一个表
不推荐使用,因为违反数据库设计原则。在子类数量众多且属性单一情况下适用。 * 每个子类用一个表 * 父类不对应表 ## 10.2实例