目录
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实例