一,持久化类
持久化类就是之前写过的实体类
持久化类必须符合javabean规范,属性必须有set和get方法;
持久化类的属性类型可以是8种基本类型或对应的包装类,通常定义包装类型,因为包装类型可以兼容null(private int id;---------private Integer id)
在对象关系映射文件(xxx.hbm.xml)中,property元素的access属性来指定访问持久化类属性的方式
access="field" 表示hibernate通过反射访问属性,可以不写set 和get方法
access="noop"表示实体类中没有对应的属性,但是数据库有
access="property" 默认值,表示hibernate通过属性的set 和get 方法访问属性
对象标识符
通常来说主键字段取名为"ID"
主键字段为整形
主键的set 方法权限设置为private,防止随意修改
二,主键生成器
主要负责我们生成数据库表中主键字段的值,通常有下面几种的配置:
(1):increment
对int,short,long的数据列生成自动增长主键
(2):identity
对SQLserver 和MySql等数据库支持自动增长的数据库
(3):sequence:
对Oracle和db2等支持序列的数据库
(4):uuid
对字符串采用uuid算法产生一个唯一的字符串主键
(5):native
根据底层的数据库支持情况自动选择identity,sequence,适合跨多种数据库的系统
若要修改主键生成器,需要在xxx.hbm.xml中配置
<id name="id" type="int">
<column name="ID" />
<generator class="native" />
</id>
三、1 vs 多
1、准备数据库和表
create table dept(
deptId int not null primary key auto_increment,
deptName varchar(20) not null
)
insert into dept values(0,'财务部');
insert into dept values(0,'开发部');
insert into dept values(0,'业务部');
insert into dept values(0,'产品部');
create table emp(
empId int not null primary key auto_increment,
deptId int references dept(deptId),
empNo char(4) not null unique,
empName varchar(20) not null,
empSex int not null,
empBirth date not null
)
insert into emp values(0,1,'E001','小明',0,'2010-10-10');
insert into emp values(0,1,'E002','小红',0,'2011-10-11');
insert into emp values(0,2,'E100','小芳',1,'2012-10-12');
insert into emp values(0,2,'E101','小王',1,'2013-10-13');
insert into emp values(0,3,'E200','小李',1,'2014-10-14');
insert into emp values(0,3,'E201','小赵',0,'2015-10-15');
2、创建maven项目
<!-- MySQL数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.2</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.17.Final</version> </dependency>
3、实体类
@Setter @Getter public class Dept { private Integer deptId;//主键 private String deptName;//部门名称 }
@Setter @Getter public class Emp { private Integer empId; //主键 private Integer deptId; //部门外键 private String empNo;//员工编号 private String empName;//员工姓名 private Integer empSex;//员工性别 private String empBirth;//员工生日 }
4、hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!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> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.password">123456</property> <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/hibernate-test?characterEncoding=utf-8</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 是否显示SQL语句 true-显示 --> <property name="hibernate.show_sql">true</property> </session-factory> </hibernate-configuration>
5、xxx.bhm.xml
Dept.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.yujun.maven.po.Dept" table="dept"> <id name="deptId" type="int"> <column name="deptId" /> <generator class="native" /> </id> <property name="deptName" type="java.lang.String"> <column name="deptName" /> </property> <!-- set就是用来配置集合属性 name:实体类中属性名 --> <set name="emps"> <!-- key用来配置外键 column:外键字段名--> <key> <column name="deptId"></column> </key> <!-- 1-多 class:配置的set集合的泛型--> <one-to-many class="com.yujun.maven.po.Emp"/> </set> </class> </hibernate-mapping>
Emp.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.yujun.maven.po.Emp" table="emp"> <id name="empId" type="int"> <column name="empId" /> <generator class="native" /> </id> <property name="empNo" type="java.lang.String"> <column name="empNo" /> </property> <property name="empName" type="java.lang.String"> <column name="empName" /> </property> <property name="empSex" type="int"> <column name="empSex" /> </property> <property name="empBirth" type="java.lang.String"> <column name="empBirth" /> </property> <!-- 多-1 name:实体类中的属性名 class:属性对应的类 --> <many-to-one name="dept" class="com.yujun.maven.po.Dept"> <!-- 外键字段 --> <column name="deptId"></column> </many-to-one> </class> </hibernate-mapping>
6、加载映射文件
在hibernate.cfg.xml中
<mapping resource="com/yujun/maven/po/Dept.hbm.xml"/> <mapping resource="com/yujun/maven/po/Emp.hbm.xml"/>
7、查询部门获取部门的所有员工
public class Demo1 { public static void main(String[] args) { // 1配置对象 Configuration config = new Configuration().configure(); // 2会话工厂 SessionFactory factory = config.buildSessionFactory(); // 3会话对象 Session session = factory.openSession(); //查询一个部门 Dept dept = session.get(Dept.class, 1);//立即发送SQL语句去数据库中查询 System.out.println(dept); //获取dept对象中所有员工信息 Set<Emp> emps = dept.getEmps(); //默认使用延迟加载(懒加载) System.out.println("1-----------------------------"); emps.forEach(System.out::println); // 关闭 session.close(); System.exit(0); } }
8、查询员工获取部门
public class Demo2 { public static void main(String[] args) { // 1配置对象 Configuration config = new Configuration().configure(); // 2会话工厂 SessionFactory factory = config.buildSessionFactory(); // 3会话对象 Session session = factory.openSession(); //查询一个员工 Emp emp = session.get(Emp.class, 2); System.out.println(emp); //这个员工的部门 Dept dept = emp.getDept(); //默认是延迟加载 System.out.println(dept); // 关闭 session.close(); System.exit(0); } }
四、级联操作和控制权
操作一个对象,会一并操作被关联的对象
比如:删除一个部门,顺带给把此部门下的所有员工删除;
增删改、这里我们只讲解级联删除;
先删除从表,再删主表(推荐)
级联操作:cascade告知hibernate对于关联的对象应该如何操作,取值:none、save-update、delete、all,默认是none-无级联操作,双方都可以配置级联操作
控制权:inverse告知hibernate对于外键的维护由谁来取得控制权;取值:true、false;
false表示控制权在己方,true-表示控制权在对方。
对于1-多关系,我们把控制权交给多的一方,也就是需要我们在1方的set节点中配置:inverse="true"
通常我们不需要配置级联操作,太危险;默认就好
dept.hbm.xml
<!-- set就是用来配置集合属性 name:实体类中属性名 cascade="delete"表示级联删除员工--> <!-- inverse="true"表示控制权,控制权控制外键由谁维护,默认是false,false-控制权在己方 true-控制权在对方 --> <set name="emps" cascade="delete" inverse="true"> <!-- key用来配置外键 column:外键字段名--> <key> <column name="deptId"></column> </key> <!-- 1-多 class:配置的set集合的泛型--> <one-to-many class="com.yujun.maven.po.Emp"/> </set>
public class Demo3 { public static void main(String[] args) { // 1配置对象 Configuration config = new Configuration().configure(); // 2会话工厂 SessionFactory factory = config.buildSessionFactory(); // 3会话对象 Session session = factory.openSession(); //4事务 Transaction tran = session.beginTransaction(); //查询一个部门 Dept dept = session.get(Dept.class, 2); //删除部门 session.delete(dept); //如果设置了级联删除,那么先删除部门对应的员工,再删除部门 //如果没有设置级联删除,那么只会删除部门,员工表的deptID字段数据被设置为null tran.commit(); // 关闭 session.close(); System.exit(0); } }
五、多-多
1、数据库和表
-- 学生表 create table student( stuId int not null primary key auto_increment, stuName varchar(20) not null ) -- 课程表 create table course( couId int not null primary key auto_increment, couName varchar(20) not null ) -- 选课表 create table xuanke( xkId int not null primary key auto_increment, studentId int references student(stuId), courseId int references course(couId) ) insert into student value(0,'小二'); insert into student value(0,'小三'); insert into course values(0,'Struts2'); insert into course values(0,'Hibernate'); insert into course values(0,'Spring'); insert into xuanke values(0,1,1); insert into xuanke values(0,1,2); insert into xuanke values(0,2,1); insert into xuanke values(0,2,2); insert into xuanke values(0,2,3);
2、实体类
@Setter @Getter public class Course { private Integer couId; private String couName; private Set<Student> stus; //多个学生 @Override public String toString() { return "Course [couId=" + couId + ", couName=" + couName + "]"; } }
@Setter @Getter public class Student { private Integer stuId; private String stuName; private Set<Course> cous; //多门课程 @Override public String toString() { return "Student [stuId=" + stuId + ", stuName=" + stuName + "]"; } }
3、xxx.hbm.xml
student.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.yujun.maven.po.Student" table="student"> <id name="stuId" type="int"> <column name="stuId" /> <generator class="native" /> </id> <property name="stuName" type="java.lang.String"> <column name="stuName" /> </property> <!-- table:表示管理的第三方的表名 --> <set name="cous" table="xuanke"> <!-- 此表在第三方表中的外键字段 --> <key> <column name="studentId"></column> </key> <!-- 多-多 column:第三方表中的外键--> <many-to-many column="courseId" class="com.yujun.maven.po.Course"></many-to-many> </set> </class> </hibernate-mapping>
course.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.yujun.maven.po.Course" table="course"> <id name="couId" type="int"> <column name="couId" /> <generator class="native" /> </id> <property name="couName" type="java.lang.String"> <column name="couName" /> </property> <!-- table:表示管理的第三方的表名 --> <set name="stus" table="xuanke"> <!-- 此表在第三方表中外键字段 --> <key> <column name="courseId"></column> </key> <!-- 多-多 column:第三方表中的外键--> <many-to-many column="studentId" class="com.yujun.maven.po.Student"></many-to-many> </set> </class> </hibernate-mapping>
需要再hibernate.cfg.xml中引用映射文件
<mapping resource="com/yujun/maven/po/Student.hbm.xml"/> <mapping resource="com/yujun/maven/po/Course.hbm.xml"/>
4、查询案例
根据一个学生,查询相应的选课
public class Demo4 { public static void main(String[] args) { // 1配置对象 Configuration config = new Configuration().configure(); // 2会话工厂 SessionFactory factory = config.buildSessionFactory(); // 3会话对象 Session session = factory.openSession(); //查询一个学生 Student student = session.get(Student.class, 2); System.out.println(student); //查询这个学生的所选的课程 Set<Course> cous = student.getCous(); cous.forEach(System.out::println); // 关闭 session.close(); System.exit(0); } }
六、1 - 1
1-1的关系,在实际开发中不是特别多,若要使用1-1关系映射,可以在双方的xxx.hbm.xml中使用<one-to-one/>进行配置