欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hibernate的第五节(组件映射、继承映射、HQL查询、Criteria查询、本地的SQL查询)

程序员文章站 2022-05-13 20:53:45
...

1>:组件映射

      需求:使用Hibernate的映射关系来描述汽车和*之间的关系

       1>:汽车的类的关系描述如下           

public class Car implements Serializable{
	private String carNum;   //汽车的车牌
	private String carName;  //汽车名字
	private Wheel wheel;     //这个是汽车的*
        setter....
        getter....
}

       2>:*的类的描述关系如下

public class Wheel implements Serializable{
	private int wheelNum;
	private String wheelName;
        setter....
        getter....
}

       3>:汽车的映射文件描述如下

<hibernate-mapping package="com.qf.componet">   
   <class name="Car" table="t_car">
     <!--配置主键-->
     <id name="carNum">
       <!--表示的是主键自己赋值-->
       <generator class="assigned"></generator>
     </id>
     <!--配置其他的字段-->
     <property name="carName"></property>
     <!--下面就配置基于组件映射-->
     <component name="wheel" class="Wheel">
        <property name="wheelName"></property>
        <property name="wheelNum"></property>
     </component>
   </class>
</hibernate-mapping>

    4>:测试文件如下

@Test
	public void testComponent() throws Exception {
		Session session=HibernateUtils.getSession();
		//执行业务逻辑
		session.save(new Car("川A:745B","宝马760",new Wheel(4,"xxxyyuu")));
		HibernateUtils.close();
	}

2>:继承映射

需求:描述动物这个类(Animal)和猫(Cat)这个类、使用Hibernate的映射关系描述出来

       1>: 简单的继承映射(就是使用一个映射文件描述一个子类)  特点:如果子类较多那么需要编写很多的映射文件

              动物类的描述    

public class Animal implements Serializable{
	private String name;   //名字
	private String color;  //颜色
        setter....
        getter....
}

            猫这个类的描述

public class Cat extends Animal  implements Serializable{
	private int weight;   //体重
	private String catchMouse;  //抓老鼠
        setter....
        getter....
}

         猫的映射文件如下

<!-- 简单的继映射 -->
<hibernate-mapping package="com.qf.extend_simple">
	<class name="Cat" table="t_cat">
		<!--配置主键 -->
		<id name="cId">
			<!--表示的是主键自己赋值 -->
			<generator class="native"></generator>
		</id>
		<!--配置其他的字段 -->
		<property name="catchMouse"></property>
		<property name="weight"></property>
		<property name="name"></property>
		<property name="color"></property>
	</class>
</hibernate-mapping>

          测试文件如下

@Test
	public void testExtend() throws Exception {
		//获取session对象
		Session session=HibernateUtils.getSession();	
		Cat cat=new Cat();
		cat.setCatchMouse("抓老鼠...");
		cat.setColor("黑红黑红");
		cat.setName("小花猫");
		cat.setWeight(5);		
		session.save(cat);	
		HibernateUtils.close();
	}

       2>:所有类(父类和所有孩子)对应一张表(特点呢:父类,所有的子类都对应了一张表、这样存在的问题是如果子类比较多的话那么这个表的字段也会不断的增多,可读性不强(官方不建议使用这种))

               动物这个类的描述如下

public class Animal implements Serializable{
	private int num;
	private String name;   //名字
	private String color;  //颜色
        setter....
        getter....
}

           猫这个类的描述如下

public class Cat extends Animal  implements Serializable{
	private int weight;   //体重
	private String catchMouse;  //抓老鼠
        setter....
       getter....
}

        狗的这个类的描述如下

public class Dog extends Animal implements Serializable{
	private String shut;
	private String catchbadPeople;
        setter....
        getter....
}

        整体(Animal.hbm.xml)的描述文件如下

<hibernate-mapping package="com.qf.extend1">
    <!--如果所有的子类数据对应一张表的话那么这里的class只能写父类的class-->
	<class name="Animal" table="t_animal">
		<!--配置主键 -->
		<id name="num">
			<!--表示的是主键自己赋值 -->
			<generator class="assigned"></generator>
		</id>
		<!--
		          这里是额外的要配置一个字段 
		           配置一个type这个字段
		    column:表示的是类别的这个名字
		-->
		<discriminator column="type_" type="string"></discriminator>
		<!--接下来就要配置子类信息了...
		    discriminator-value:表示的是给type字段添加的这个额外的值(自动完成的)
		-->	
		<!--配置其他的字段 -->
		<property name="name"></property>
		<property name="color"></property>	
		<subclass name="Cat" discriminator-value="cat_">
		   <!--这个里面就配置猫特有的字段了-->
		   <property name="catchMouse"></property>
		   <property name="weight"></property>
		</subclass>		
		<!--配置狗的这个字段-->
		<subclass name="Dog" discriminator-value="dog_">
		   <!--这个里面就配置猫特有的字段了-->
		   <property name="shut"></property>
		   <property name="catchbadPeople"></property>
		</subclass>
	</class>
</hibernate-mapping>

             测试文件如下

@Test
	public void testExtend() throws Exception {
		//获取session对象
		Session session=HibernateUtils.getSession();
		/*Cat cat=new Cat();
		cat.setCatchMouse("抓老鼠");
		cat.setColor("黑色");
		cat.setName("小黄");
		cat.setWeight(5);
		cat.setNum(123);*/
		
		Dog dog=new Dog();
		dog.setCatchbadPeople("抓坏人..");
		dog.setColor("黑黄黑黄的");
		dog.setName("小黑子");
		dog.setNum(2222);
		dog.setShut("叫");
		session.save(dog);
		HibernateUtils.close();
	}

       3>:所有类(父类 和  孩子) 都分别对应表(特点:是父类也对应表、子类也有自己的表、那么这种情况下的话、增加了查询的复杂度、父类本与业务无关但是也对应表)

                动物这个类的描述和上面一样

                猫这个类的描述也和上面一样

               狗的描述也和上面一样

                整个的映射文件的描述如下

<hibernate-mapping package="com.qf.extend2">
    <!--如果所有的子类数据对应一张表的话那么这里的class只能写父类的class-->
	<class name="Animal" table="t_animal">
		<!--配置主键 -->
		<id name="num">
			<!--表示的是主键自己赋值 -->
			<generator class="native"></generator>
		</id>
		
		<!--配置其他的字段 -->
		<property name="name"></property>
		<property name="color"></property>
		
		<!--下面咋们就的配置子类的问题了-->
		<joined-subclass name="Cat" table="t_cat">
		   <!--映射上面的这个父类的主键  他就会直接映射到上面的class的类上面去-->
		   <key column="num"></key>
		   <!--映射普通的字段-->
		   <property name="catchMouse"></property>
		   <property name="weight"></property>
		</joined-subclass>
		
		<joined-subclass name="Dog" table="t_dog">
		   <!--映射上面的这个父类的主键  他就会直接映射到上面的class的类上面去-->
		   <key column="num"></key>
		   <!--映射普通的字段-->
		   <property name="catchbadPeople"></property>
		   <property name="shut"></property>
		</joined-subclass>
	</class>
</hibernate-mapping>

               测试文件如下

@Test
	public void testExtend() throws Exception {
		//获取session对象
		Session session=HibernateUtils.getSession();
		
		Cat cat=new Cat();
		cat.setCatchMouse("抓老鼠");
		cat.setColor("黑色");
		cat.setName("小黄");
		cat.setWeight(5);
		cat.setNum(123);
		
		/*Dog dog=new Dog();
		dog.setCatchbadPeople("抓坏人..");
		dog.setColor("黑黄黑黄的");
		dog.setName("小黑子");
		dog.setNum(2222);
		dog.setShut("叫");*/
		
		session.save(cat);
		HibernateUtils.close();
	}

       4>:父类不对应表孩子对应表(官方推荐的一种继承映射的玩法)

              

                动物这个类的描述和上面一样

                猫这个类的描述也和上面一样

               狗的描述也和上面一样

               整体的描述关系如下      

<hibernate-mapping package="com.qf.extend3">
    <!--如果所有的子类数据对应一张表的话那么这里的class只能写父类的class-->
    <!--
        abstract:true就表示的是当前对象不对应表
    -->
	<class name="Animal" abstract="true">
		<!--配置主键 -->
		<id name="num">
			<!--表示的是主键自己赋值   这里记住主键的增长模式不能是 自增-->
			<generator class="assigned"></generator>
		</id>
		
		<!--配置其他的字段 -->
		<property name="name"></property>
		<property name="color"></property>
		
		<!--下面咋们就的配置子类的问题了-->
		<union-subclass name="Cat" table="t_cat">
		  <property name="catchMouse"></property>
		  <property name="weight"></property>
		</union-subclass>
		<union-subclass name="Dog" table="t_dog">
		  <property name="shut"></property>
		  <property name="catchbadPeople"></property>
		</union-subclass>
	</class>
</hibernate-mapping>

            测试文件如下

@Test
	public void testExtend() throws Exception {
		//获取session对象
		Session session=HibernateUtils.getSession();
		/*
		Cat cat=new Cat();
		cat.setCatchMouse("抓老鼠");
		cat.setColor("黑色");
		cat.setName("小黄");
		cat.setWeight(5);
		cat.setNum(123);*/
		
		Dog dog=new Dog();
		dog.setCatchbadPeople("抓坏人..");
		dog.setColor("黑黄黑黄的");
		dog.setName("小黑子");
		dog.setNum(2222);
		dog.setShut("叫");
		
		session.save(dog);
		HibernateUtils.close();
	}

3>:HQL查询(Hibernate Query Language)  重点掌握

      HQL查询和本地SQL查询的区别和联系

            HQL查询是基于对象和对象的属性来进行的  

            SQL查询是基于表和表中的列来进行的

            也就是说HQL是跨数据库的只要对象没变那么代码就不需要改变   SQL是不能跨数据库的 只要底层的数据库改变了 有可能SQL就会改变

            SQL的运行效率高  HQL的运行要经过翻译这个过程、所以效率相对来说比较低

      HQL的使用如下

       @Test
	public void testOne2Many() throws Exception {
		//针对于查询而已
		//get方法实现查询   ----> 默认不支持懒加载
		//load方法实现查询 ---->默认是支持懒加载
		
		//HQL查询
		Session session=HibernateUtils.getSession();
		
		//查询整个表的数据(在HQL语句中没有 select *这种写法)
		//查询整个表
		//Query q=session.createQuery("from Dept");
		//Query q=session.createQuery("select d from Dept d");
		
		//查询指定的列
		
		//Query q=session.createQuery("select d.dName,d.dAddress from Dept d");
//		Query q=session.createQuery("select dName,dAddress from Dept");
		
		//直接将查询回来的数据风格装成JAVA对象
		//Query q=session.createQuery("select new Dept(dName,dAddress) from Dept");
		
		
		//统计查询
		//Query q=session.createQuery("select count(*) from Employee");
		//如果查询回来结果是唯一的那么就使用下面的方式来接受这个结果
		//Object object=q.uniqueResult();
        //System.out.println(object);
		
		
		//分组统计  e.dept实际上使用的相当于是这个关系  要使用这个的前提是必须要有关系才行
		//Query q=session.createQuery("select count(*),e.dept from Employee e group by e.dept");
		
		
		//带有条件的查询(第一种 通过占位符来玩)
		//Query q=session.createQuery("select d from Dept d where d.dId<?");
		//下面的这种模式的下标是从0开始的
		//q.setInteger(0,2);
		
		//通过取别名来编写查询语句(:名字  / 取别名)
//		Query q=session.createQuery("select d from Dept d where d.dId<:dId");
//		q.setParameter("dId",2);
		
		
		//多条件查询
//		Query q=session.createQuery("select d from Dept d where d.dId<:dId and d.dName=:dName");
//		q.setParameter("dId",10);
//		q.setParameter("dName","JAVA教学部");
		
		//模糊查询
//		Query q=session.createQuery("select d from Dept d where d.dName like ?");
//		q.setString(0,"%保%");
		
		
		//内连接查询
		//Query q=session.createQuery("from Employee e inner join e.dept");
		
		//左外连接
//		Query q=session.createQuery("from Dept d left join d.emps");
		
		//右外连接
//		Query q=session.createQuery("from Employee e right join e.dept");
		
		//迫切左外连接	
//		Query q=session.createQuery("from Employee e left join fetch e.dept");
		
		
		//迫切右外连接
//		Query q=session.createQuery("from Dept d right join fetch d.emps");
		
		Query q=session.getNamedQuery("getDept");
		
		System.out.println(q.list());
		HibernateUtils.close();
	}


4>:Criteria查询(QBC查询Query by Criteria)有这个印象就好

@Test
	public void testQBC() throws Exception {
		Session session=HibernateUtils.getSession();
		
		//后面的这个参数 是你要查询那个对象那么你就写那个类的字节码对象
		Criteria criteria=session.createCriteria(Dept.class);
		
		
		Map<String,Object> maps=new HashMap<String,Object>();
		maps.put("dId",1);
		maps.put("dName","JAVA教学部");
		//在Critiria查询中 条件的添加
		
		Criterion criterion=Restrictions.allEq(maps);
		
		List list=criteria.list();
		
		System.out.println(list);
		
		HibernateUtils.close();
	}

5>:本地的SQL查询(掌握)

      @Test
	public void testNativeSql() throws Exception {
		Session session=HibernateUtils.getSession();
		SQLQuery query=session.createSQLQuery("select * from t_dept");
		System.out.println("数据:"+query.list());
		
		HibernateUtils.close();
	}
     注意:上面的三个查询中 HQL和本地的SQL是需要掌握的 QBC查询有这个意识就好了、因为复杂的查询HQL搞不定那么只能借助本地的SQL查询来实现