文章目录
Hibernate
定义:
Hibernate是一个开发源代码的对象关系映射框架。它对jdbc进行了非常轻量级的对象封装,它将POJO(简单的Java对象,实际就是普通JavaBeans)与数据库建立映射关系,是一个全自动的orm框架,hibernate可以自动生成sql语句,自动执行,使java程序员可以随心所欲的使用java对象编程操作数据库。hibernate可以应用任何使用jdbc的场景,既可以在java客户端使用,也可以在web中使用。
orm:
对象关系映射(Object Relational Mapping)通过使用描述对象和数据库之间的元数据,将面向对象语言程序中的对象自动持久化到关系型数据库中。本质上就是将一种形式转换到另外一种形式,通俗讲就是我们通过操作Java对象,就可以完成对数据库表的操作,我们在具体的操作业务对象的时候,就不需要再去和复杂的sql语句打交道,只要像平时一样操作对象就可以了。
hibernate 对象OID:
我们都知道虚拟机内存区分了两个对象是看内存地址是否一致,数据库区分两个对象,靠的是表的主键。hibernate负责把内存中的对象持久化到数据库中,靠的就是对象标识符来区分两个对象是否相同。实体类中映射主键的字段oid,在映射文件中对应数据库主键的属性。
Hibernate中Java对象有哪些状态?
1、瞬时状态:刚New的一个对象,没有放在Session时,也没有存储在数据库中。
2、持久化状态:对象存储在数据库中,并且存在于Session会话中。
3、游离状态:对象存储在数据库中,但已经不存在于Session会话中。
Hibernate的优缺点
优点:
1、简化了jdbc繁琐的编码
2、对面面向对象特性支持良好
3、可移植性好
缺点:
1、不合适需要使用数据库的特定优化机制的情况
2、不合适大规模的批量数据处理
与MyBatis的比较:
1、相对于MyBatis的"SQL-Mapping"的orm实现,Hibernate的orm实现更加完善,提供了对象状态的管理、级联操作等功能。
2、完全面向对象,语句与数据库无关,无需关注SQL的生成,开发简单便于修改,数据库移植性好。
3、由于直接使用SQL,MyBatis使用自由度高
搭建Hibernate环境
1、导入jar包
2、在src下创建映射配置文件:hibernate.cfg.xml
<!-- 对hibernate全局配置 -->
<hibernate-configuration>
<session-factory>
<!-- 配置数据库连接 -->
<property name="connection.driver_class">
oracle.jdbc.driver.OracleDriver
</property>
<property name="connection.url">
jdbc:oracle:thin:@127.0.0.1:1521:xe
</property>
<property name="connection.username">huminjie</property>
<property name="connection.password">123456</property>
<!-- 显示hibernate在运行的时候执行的sql语句,并且格式化 -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- 配置方言,简单讲就是告诉数据库,hibernate配置-->
<property name="dialect">
org.hibernate.dialect.Oracle10gDialect
</property>
<!-- 配置session会话的作用域于当前线程 -->
<property name="current_session_context_class">thread</property>
<!-- 配置hibernate的映射文件,后期还有很多个需要引入 -->
<mapping resource="com/hibernate/entity/Dept.hbm.xml"/>
</session-factory>
</hibernate-configuration>
3、创建持久化类和映射文件
持久化类(实现ava.io.Serializable 接口)
package com.hibernate.entity;
import java.io.Serializable;
public class Dept implements Serializable{
private Integer deptNo; //部门id
private String dname; //部门名称
private String loc; //部门地址
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept [deptNo=" + deptNo + ", dname=" + dname + ", loc=" + loc + "]";
}
public Dept(Integer deptNo, String dname, String loc) {
super();
this.deptNo = deptNo;
this.dname = dname;
this.loc = loc;
}
public Dept() {
super();
}
}
Dept.hbm.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-mapping>
<!-- 建立对象与表的映射 -->
<!--
dynamic-insert="true":设置对象中没有值的字段 insert并不会对其进行插入,数值型除外
dynamic-update="true":只对进行了改变的值进行更新
-->
<class name="com.hibernate.entity.Dept" table="dept" dynamic-insert="true" dynamic-update="true">
<!--id是配置实体类和数据库主键的关联 -->
<id name="deptNo" column="deptno" type="java.lang.Integer">
<!--oracle数据库序列自增 -->
<generator class="sequence">
<!-- 配置序列 -->
<param name="sequence">dept_deptno_seq</param>
</generator>
</id>
<!-- 建立类中的普通属性和表中的字段相对应 -->
<!-- 第一种方式 -->
<property name="dname" column="dname" type="java.lang.String" />
<!-- 第 二种方式 -->
<property name="loc" type="java.lang.String">
<column name="loc">
</property>
</class>
</hibernate-mapping>
单元测试
package com.test;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.hibernate.entity.Dept;
public class HBTest{
@Test
public void hbTest01(){
//加载Hibernate配置文件
Configuration conf = null;
//创建Session工厂
SessionFactory sf = null;
//创建session对象,实施持久
Session session = null;
//事务处理
Transaction tx = null;
try{
//如果不指定参数,默认加载src/目录下名为hibernate.cfg.xml
conf = new Configuration().configure();
//获取当前session
sf = conf.buildSessionFactory();
session = sf.getCurrentSession();
//开启事务处理
tx = session.beginTransaction();
//创建对象
Dept dept = new Dept(110,"治安部","南昌市高新区");
//执行插入对象
session.save(dept);
//提交事务
tx.commit();
}catch(Exception e){
e.printStackTrace();
if(tx!=null){
//如果try发生异常,则事务回滚
tx.roolback();
}
}finally{
//释放资源
}
}
}
封装HibernateUtil工具类:返回session
package com.hibernate.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* 封装工具类
* @author hmj
*
*/
public class HibernateUtil {
private static Configuration conf = null;
private static SessionFactory sf = null;
static{
try{
//如果不指定参数,默认加载src/目录下名为hibernate.cfg.xml
conf = new Configuration().configure();
//获取当前session
sf = conf.buildSessionFactory();
}catch(Exception e){
e.printStackTrace();
}
}
private HibernateUtil() {}
public static Session currentSession(){
//返回session
return sf.getCurrentSession();
}
}
Hibernate 操作数据
增加
save()
HibernateUtil.currentSession().save(dept);
删除
delete()
HibernateUtil.currentSession().delete(dept);
根据查询id删除
HibernateUtil.currentSession().delete(HibernateUtil.currentSession().load(Dept.class,id));
修改
1、merge():合并,如果参数和数据库数据不一致则修改
HibernateUtil.currentSession().merge(dept);
2、update():不管参数的和数据库是否一致,都会修改
HibernateUtil.currentSession().update(dept);
3、saveOrUpdate():如果有主键就是修改,没有主键就是插入语句
HibernateUtil.currentSession().saveOrUpdate(dept);
查询
OID检索:根据主键获取对象
1、get():会去确认该id对应的数据是否存在,如果没有就返回null
(Dept) HibernateUtil.currentSession().get(Dept.class, id);
2、load():会根据lazy属性值来确定是否使用延迟加载(默认延迟加载),如果没有就抛出异常
(Dept) HibernateUtil.currentSession().load(Dept.class,id);
hibernate支持不同的查询方式:
1、HQL(Hibernate Query Language)Hibernate查询语言
是一种面向对象的查询语言,查询的是对象以及对象的属性【区分大小写】
2、SQL (Structured Query Language)结构化查询语言
查询的是表以及列【不区分大小写】,比较灵活,用于支持HQL语句不支持的非常复杂的SQL语句,但迁移性差(比如项目oracle改为mysql)
3、QBC(Query By Criteria)查询条件
API提供了检索对象的另一种方式,它主要由Criteria接口、Criterion接口和Expresson类组成,它支持在运行时动态生成查询语句。
HQL
1、查询Emp对象的list集合(一次性查询完)
HibernateUtil
.currentSession()
//Emp:实体类类名
.createQuery(" from Emp ")
.list();
2、查询Emp对象的iterator集合(逐个查询)
HibernateUtil
.currentSession()
//Emp:实体类类名
.createQuery(" from Emp ")
.iterate();
3、条件查询Emp对象的list集合
HibernateUtil
.currentSession()
//Emp:实体类类名
.createQuery(" from Emp where job = ?")
.setString(0, job)
.list();
4、查询工资排名前三
HibernateUtil
.currentSession()
.createQuery("from Emp order by salary desc")
//setMaxResults(3):设置最大结果数为3
.setMaxResults(3)
.list();
5、分页查询
HibernateUtil
.currentSession()
.createQuery("from Emp order by id")
//pageNo:当前页数,pagSize:页面尺寸
.setFirstResult((pageNo-1)*pagSize)
.setMaxResults(pagSize)
.list();
SQL
1、查询聚合函数
(Long) HibernateUtil
.currentSession()
//empNo:表字段名
.createQuery("select count(empNo) from Emp")
//uniqueResult():返回唯一结果
.uniqueResult();
2、查询对象的list集合
HibernateUtil
.currentSession()
//emp:表名
.createSQLQuery("select * from emp")
.addEntity(Emp.class)
.list();
3、根据条件查询对象
(Emp) HibernateUtil
.currentSession()
.createSQLQuery("select * from emp where empno = ?")
//通过实体类给条件赋值
.addEntity(Emp.class)
.setInteger(0, empno)
.list()
.get(0);
QBC
1、查询对象的list集合
HibernateUtil
.currentSession()
.createCriteria(Emp.class)
.list();
2、模糊查询对象
HibernateUtil
.currentSession()
.createCriteria(Emp.class)
//empName为实体类的属性名
.add(Restrictions.like("empName","%"+ename+"%"))
.list();
3、分页查询
HibernateUtil
.currentSession()
.createCriteria(Emp.class)
//(1)设置开始的位置,开始位置从0开始,第三条数据的下标为2
.setFirstResult(2)
//(2)设置每页的记录数,每页返回的数据时4条,设置为4
.setMaxResults(4)
.list();
Hibernate 关联映射
配置映射:
Emp:多对一
package com.hibernate.entity;
import java.io.Serializable;
import java.util.Date;
public class Emp implements Serializable {
private String empName;
private Integer empNo;
private Date hireDate;
private String job;
private Double salary;
//多对一,多个员工可能在一个部门下
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Integer getEmpNo() {
return empNo;
}
public void setEmpNo(Integer empNo) {
this.empNo = empNo;
}
public Date getHireDate() {
return hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Emp [empName=" + empName + ", empNo=" + empNo + ", hireDate=" + hireDate + ", job=" + job + ", salary="
+ salary + "]";
}
public Emp(String empName, Integer empNo, Date hireDate, String job, Double salary) {
super();
this.empName = empName;
this.empNo = empNo;
this.hireDate = hireDate;
this.job = job;
this.salary = salary;
}
public Emp() {}
}
Emp.hbm.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">
<hibernate-mapping>
<class name="com.hibernate.entity.Emp" table="EMP">
<id name="empNo" column="EMPNO" type="java.lang.Integer">
<generator class="increment"/>
</id>
<property name="empName" type="java.lang.String" column="ENAME"/>
<property name="job" type="java.lang.String" column="JOB"/>
<property name="salary" type="java.lang.Double" column="SAL"/>
<property name="hireDate" type="java.util.Date"/>
<!--多对一关系 -->
<many-to-one name="dept" class="com.hibernate.entity.Dept" column="DEPTNO"/>
</class>
</hibernate-mapping>
Dept:一对多
package com.hibernate.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Dept implements Serializable{
private Integer deptNo; //部门id
private String dname; //部门名称
private String loc; //部门地址
//一个部门下可能有多个员工,一对多
private Set<Emp> emps = new HashSet<Emp>();
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
}
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept [deptNo=" + deptNo + ", dname=" + dname + ", loc=" + loc + ", emps=" + emps + "]";
}
public Dept(Integer deptNo, String dname, String loc) {
super();
this.deptNo = deptNo;
this.dname = dname;
this.loc = loc;
}
public Dept(String dname, String loc) {
super();
this.dname = dname;
this.loc = loc;
}
public Dept() {
super();
}
}
Dept.hbm.xml:一对多关系
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<!-- name是Dept实体类全路径 table是数据库表名 -->
<!-- dynamic-insert或 dynamic-update值为true的时候,如果你没有修改或增加该字段,该字段不会再sql执行,提高了效率-->
<class name="com.hibernate.entity.Dept" table="dept" dynamic-insert="true" dynamic-update="true">
<!--
id是配置实体类和数据库主键的关联
name值Dept实体类的deptNo字段,column指数据库表的deptno主键
-->
<id name="deptNo" column="deptno" type="java.lang.Integer">
<!-- <generator class="sequence">
<param name="sequence">my_seq</param>
</generator> -->
</id>
<property name="dname" column="dname" type="java.lang.String" />
<property name="loc" type="java.lang.String">
<column name="loc" />
</property>
<!-- 一对多关系 -->
<!-- 一inverse:true不会帮你维护关系 -->
<set name="emps" cascade="all" inverse="true">
<key column="deptno"></key>
<one-to-many class="com.hibernate.entity.Emp" />
</set>
</class>
</hibernate-mapping>
Employee:多对多
package com.hibernate.entity;
import java.util.HashSet;
import java.util.Set;
public class Employee {
private Integer empId; //雇员id
private String empName; //雇员名字
//多个雇员可能有多个项目,多对多
private Set<Project> projects=new HashSet<Project>( );
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Set<Project> getProjects() {
return projects;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", empName=" + empName + ", projects=" + projects + "]";
}
public Employee(Integer empId, String empName) {
super();
this.empId = empId;
this.empName = empName;
}
public Employee() {
super();
}
}
Employee.hbm.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">
<hibernate-mapping>
<class name="com.hibernate.entity.Employee" table="employee" dynamic-insert="true" dynamic-update="true">
<id name="empId" column="empid" type="java.lang.Integer">
<generator class="assigned"/>
</id>
<property name="empName" type="java.lang.String" column="empname"/>
<!--
name:本类属性名称
table:关系表(中间表)
cascade="save-update":表示级联操作,
inverse:用于指示本方是否参与维护关系(关联两张表),true时不维护,false时维护。
-->
<set name="projects" table="proemp" cascade="save-update" inverse="true">
<!-- column:当前对象在中间表的外键的名称 -->
<key column="rempid"></key>
<!-- class:另一个bean的全限类名,column为其连接的外键 -->
<many-to-many class="com.hibernate.entity.Project" column="rproid"/>
</set>
</class>
</hibernate-mapping>
Project:多对多
package com.hibernate.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
public class Project implements Serializable{
private Integer proId; //项目id
private String proname ; //项目名称
//多个项目可能有多个雇员,多对多
private Set<Employee> employees=new HashSet<Employee>();
public Integer getProId() {
return proId;
}
public void setProId(Integer proId) {
this.proId = proId;
}
public String getProname() {
return proname;
}
public void setProname(String proname) {
this.proname = proname;
}
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
@Override
public String toString() {
return "Project [proId=" + proId + ", proname=" + proname + "]";
}
public Project(Integer proId, String proname) {
super();
this.proId = proId;
this.proname = proname;
}
public Project() {
super();
}
}
Project.hbm.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">
<hibernate-mapping>
<class name="com.hibernate.entity.Project" table="project" dynamic-insert="true" dynamic-update="true">
<id name="proId" column="proid" type="java.lang.Integer">
<generator class="assigned"/>
</id>
<property name="proname" type="java.lang.String" column="proname"/>
<!--
name:本类属性名称
table:关系表(中间表)
cascade="save-update":表示级联操作,
inverse:用于指示本方是否参与维护关系(关联两张表),true时不维护,false时维护。
-->
<set name="employees" table="proemp" cascade="save-update">
<!-- 自身连接外面的外键 -->
<key column="rproid"></key>
<!-- class:另一个bean的全限类名,column为其连接的外键 -->
<many-to-many class="com.hibernate.entity.Employee" column="rempid"/>
</set>
</class>
</hibernate-mapping>
Hibernate的聚合函数查询
//聚合函数查询
@Test
public void test7() {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
//查询每个岗位的员工数
//String hql = "select e.job,count(*) from Emp e group by e.job";
//查询每个岗位的最高、最低工资
//String hql = "select e.job,max(e.salary),min(e.salary) from Emp e // where e.job is not null group by e.job ";
//查询部门平均工资大于500的部门
String hql = "select e.dept.dname,avg(salary) from Emp e group by e.dept.dname having avg(salary)>500";
List<Object[]> result = session.createQuery(hql).list();
for (Object[] row : result) {
System.out.println(row[0]+"\t"+row[1]+"\t"+row[2]);
}
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if(tx!=null){
tx.rollback();
}
}
}
Hibernate的连接查询
左连接
//左连接
@Test
public void test1() {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
//查询部门下的员工信息
//sql:select * from dept d left join emp e on d.deptno=e.deptno
//注意,Dept是类名
String hql = "from Dept d left join d.emps e ";
//返回size为2的对象集合, 下标0的是主表,下标1的是连接表
List<Object[]> result = session.createQuery(hql).list();
for (Object[] row : result) {
Dept dept = (Dept) row[0];
System.out.println(dept.getDname());
Emp emp = (Emp) row[1];
System.out.println(emp==null?"null":emp.getEmpName());
System.out.println("---------------------");
}
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if(tx!=null){
tx.rollback();
}
}
}
迫切左连接
//迫切左连接
@Test
public void test3_2() {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
//查询部门下的员工信息
//sql:select * from dept d left join emp e on d.deptno=e.deptno
//注意,Dept是类名
//迫切连接的作用是查询Dept表时就把该部门下的员工给查询出来(相当于lazy=false)它的到的是Dept类型的集合
String hql = "from Dept d left join fetch d.emps e ";
List<Dept> result = session.createQuery(hql).list();
for (Dept dept : result) {
System.out.println(dept.getDname());
if(dept.getEmps().size()>0){
for (Emp emp : dept.getEmps()) {
System.out.println("\t"+emp.getEmpName());
}
}
}
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if(tx!=null){
tx.rollback();
}
}
}
内连接
//内连接
@Test
public void test2() {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
//查询部门下的员工信息
//sql:select * from dept d left join emp e on d.deptno=e.deptno
//注意,Dept是类名
String hql = "from Dept d inner join d.emps e ";
List<Object[]> result = session.createQuery(hql).list();
for (Object[] row : result) {
Dept dept = (Dept) row[0];
System.out.println(dept.getDname());
Emp emp = (Emp) row[1];
System.out.println(emp==null?"null":emp.getEmpName());
System.out.println("---------------------");
}
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if(tx!=null){
tx.rollback();
}
}
}
等值连接
@Test
public void test4() {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
//查询部门下的员工信息
//sql:select * from dept d left join emp e on d.deptno=e.deptno
//注意,Dept是类名
String hql = "from Dept d,Emp e where e.dept=d ";
List<Object[]> result = session.createQuery(hql).list();
for (Object[] row : result) {
Dept dept = (Dept) row[0];
System.out.println(dept.getDname());
Emp emp = (Emp) row[1];
System.out.println(emp==null?"null":emp.getEmpName());
System.out.println("---------------------");
}
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if(tx!=null){
tx.rollback();
}
}
}
隐式等值连接
@Test
public void test5() {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
//查询部门下的员工信息
//sql:select * from dept d left join emp e on d.deptno=e.deptno
//注意,Dept是类名
String hql = "from Emp e where e.dept.dname='操作部' ";
List<Object[]> result = session.createQuery(hql).list();
for (Object[] row : result) {
Dept dept = (Dept) row[0];
System.out.println(dept.getDname());
Emp emp = (Emp) row[1];
System.out.println(emp==null?"null":emp.getEmpName());
System.out.println("---------------------");
}
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if(tx!=null){
tx.rollback();
}
}
}
Hibernate的子查询
//子查询
@Test
public void test8() {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.currentSession();
tx = session.beginTransaction();
String hql = "from Emp e where e.salary>(select avg(salary) from Emp)";
List<Emp> result = session.createQuery(hql).list();
for (Emp emp : result) {
System.out.println(emp.getEmpName());
}
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if(tx!=null){
tx.rollback();
}
}
}
注解配置
作用:Hibernate提供了注解来代替hbm.xml文件完成对象关系映射
1、使用注解配置持久化类以及对象关联关系
多对一:Emp.java
package com.hibernate.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.hibernate.annotations.GenericGenerator;
/**
* 注解有两种,一种是jpa提供,jpa是jdk提供orm的支持
* 另外一种是hibernate提供的,功能更强,是对jpa色补充,比
* @author hmj
*
*/
//name指定的是这个实体类映射的数据库的Emp表
@Entity
//如果不写@Table,数据库表名应该和JavaBean类名Emp一致
@Table(name = "Emp")
public class Emp implements Serializable {
@Id
// 如果只写了@Id没有加任何主键生成规则,那么默认assigned
// 方式1 生成increment
// @GeneratedValue(generator = "INC_EMPNO")
// @GenericGenerator(strategy = "increment",name = "INC_EMPNO")
//方式2 生成oracle数据库
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "SEQ_EMPNO")
@SequenceGenerator(sequenceName = "emp_empno_seq",name = "SEQ_EMPNO")
private Integer empNo; //员工编号
//@Column作用:如果不加@Column,那么默认以为你的数据库字段和属性名同名
//name的值是数据库中的字段名
@Column(name="ENAME")
private String empName; //员工姓名
@Column(name="HIREDATE")
private Date hireDate; //入职时间
@Column(name="JOB")
private String job; //职位
@Column(name="SAL")
private Double salary; //月薪
//@Transient忽略属性映射,数据库中没有该字段,不能映射就使用@Transient
@Transient
private String from;
@Transient
private String to;
//EAGER是立即加载,LAZY延迟加载
//以面向对象的方式配置多对一关系
@ManyToOne(targetEntity = Dept.class,fetch = FetchType.LAZY)
//@JoinColumn指定外键列
@JoinColumn(name = "DEPTNO")
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Integer getEmpNo() {
return empNo;
}
public void setEmpNo(Integer empNo) {
this.empNo = empNo;
}
public Date getHireDate() {
return hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Emp [empName=" + empName + ", empNo=" + empNo + ", hireDate=" + hireDate + ", job=" + job + ", salary="+ salary + "]";
}
public Emp(String empName, Integer empNo, Date hireDate, String job, Double salary) {
super();
this.empName = empName;
this.empNo = empNo;
this.hireDate = hireDate;
this.job = job;
this.salary = salary;
}
public Emp() {}
}
一对多:Dept.java
package com.hibernate.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.hibernate.annotations.Cascade;
@Entity
@javax.persistence.Table(name = "Dept")
public class Dept implements Serializable{
@Id
private Integer deptNo; //部门id
@Column(name="DNAME")
private String dname; //部门名称
@Column(name="LOC")
private String loc; //部门地址
// 默认fetch = FetchType.LAZY
// 定义一对多关系
// mappedBy表示声明自己不是一对多的关系维护端,由对方来维护,是在一的一方进行声明的。mappedBy的值应该为一的一方的表名。
// @OneToMany(targetEntity = Emp.class,mappedBy = "dept",fetch = FetchType.LAZY,cascade = {CascadeType.ALL})
@OneToMany(mappedBy = "dept",targetEntity = Emp.class)
@Cascade({
org.hibernate.annotations.CascadeType.SAVE_UPDATE,
org.hibernate.annotations.CascadeType.DELETE,
org.hibernate.annotations.CascadeType.MERGE
})
private Set<Emp> emps = new HashSet<Emp>();
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
}
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "Dept [deptNo=" + deptNo + ", dname=" + dname + ", loc=" + loc + "]";
}
public Dept(Integer deptNo, String dname, String loc) {
super();
this.deptNo = deptNo;
this.dname = dname;
this.loc = loc;
}
public Dept(String dname, String loc) {
super();
this.dname = dname;
this.loc = loc;
}
public Dept() {
super();
}
}
多对多:Project.java
package com.hibernate.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
@Entity
@Table(name="project")
public class Project implements Serializable{
@Id
private Integer proId;
private String proname ;
// 多对多
@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
// 使用JoinTable来描述中间表,并描述中间表中外键与Project,Employee的映射关系
// joinColumns它是用来描述Project与中间表中的映射关系
// inverseJoinColums它是用来描述Employee与中间表中的映射关系
@JoinTable(name="PROEMP",
joinColumns = {@JoinColumn(name = "RPROID")},
inverseJoinColumns = {@JoinColumn(name = "REMPID")}
)
private Set<Employee> employees=new HashSet<Employee>();
public Integer getProId() {
return proId;
}
public void setProId(Integer proId) {
this.proId = proId;
}
public String getProname() {
return proname;
}
public void setProname(String proname) {
this.proname = proname;
}
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
@Override
public String toString() {
return "Project [proId=" + proId + ", proname=" + proname + "]";
}
public Project(Integer proId, String proname) {
super();
this.proId = proId;
this.proname = proname;
}
public Project() {
super();
}
}
多对多:Employee.java
package com.hibernate.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import org.hibernate.annotations.GenericGenerator;
@Entity
public class Employee {
@Id
private Integer empId;
@Column(name = "EMPNAME")
private String empName;
//多对多
@ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinTable(name="PROEMP",
joinColumns = {@JoinColumn(name="REMPID")},
inverseJoinColumns = {@JoinColumn(name="RPROID")}
)
private Set<Project> projects=new HashSet<Project>( );
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Set<Project> getProjects() {
return projects;
}
public void setProjects(Set<Project> projects) {
this.projects = projects;
}
@Override
public String toString() {
return "Employee [empId=" + empId + ", empName=" + empName + ", projects=" + projects + "]";
}
public Employee(Integer empId, String empName) {
super();
this.empId = empId;
this.empName = empName;
}
public Employee() {
super();
}
}
2、在Hibernate配置文件(hibernate.cfg.xml)中声明持久化类
<mapping class="持久化类完整限定名" />
补充
主键生成策略
https://blog.csdn.net/mmake1994/article/details/81506893
懒加载
定义:当用到数据的时候才向数据库查询
true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其
集合元素的数据
false:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据
extra:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据
详细:https://www.cnblogs.com/loaderman/p/10037878.html