orm框架----Hibernate

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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值