22-Java-Hibernate框架(二)

Hibernate的了解、Hibernate的搭建、Hibernate的基本使用流程等内容请阅读21-Java-Hibernate框架(一)

五、Hibernate的Query查询接口(重中之重)

  1.HQL语言了解:Hibernate Query Language(HQL),是hibernate的查询语言,和SQL语句结构一样,不同点注意点如下:

      (1)HQL是面向对象查询,SQL是面向结构查询

      (2)在HQL使用类名和属性名,替代了原有的表名和字段名  

      (3)在HQL语句中类型名和属性名大小写敏感  

      (4)如果需要select * 查询所有字段的值,在HQL语句中可以省略select *语句。例如:from User;

      (5)如果需要join...on表连接,需要建立关联映射关系使用,不支持on子句

      (6)不要使用数据库提供的字符串函数、日期函数和一些特有的函数。一些基础的函数可以使用,例如:max(),min(),sum(),avg(),count()等。

      (7)若只查询字体类中某几个字段,返回的结果是泛型,值的集合

  2.具体Query常用的相关接口看代码演示

 1 package com.hibernatetest.test;
 2 
 3 import java.util.List;
 4 
 5 import org.hibernate.Query;
 6 import org.hibernate.Session;
 7 import com.hibernatetest.entity.User;
 8 import HibernatenateUtils.hibernateUtils;
 9 /*
10  * Query接口的常用方法:
11  *             1.setXXX():用于设置HQL语句中问号或变量的值
12  *             2.uniqueResult():得到单个对象(返回Object类型),在已知查询结果中只有一个或零个才能用此函数,若有多个满足条件的结果则报异常
13  *             3.executeUpdate():执行更新和删除语句(返回int型作为操作成功的次数)
14  *             4.分页查询
15  *             5.list():获取结果集(返回List类型)
16  *             6.iterate():获取结果集(返回Iterator类型)
17  * */
18 public class QueryTest {
19     public static void main(String[] args) {
20         //第一步:Query对象是通过Session获取的,所以先要通过之前写hibernate工具类获取Session对象
21         Session    session = hibernateUtils.getSession();
22         
23         //第二步:CreateQuery("HQL语句"):用于创建Query对象。
24         Query query = session.createQuery("from User where uname='zhangsan'");
25         
26         /*查询参数设值setXXX(): (两种方式)
27          * 1.问号设值
28          *             Query query = session.createQuery("from User where uid between ? and ?");
29          *             query.setInteger(0,5);//给第一个问号处赋值5
30          *             query.setInteger(1,10);//给第一个问号处赋值10
31          *             
32          * 2.变量设值
33          *             Query query = session.createQuery("from User where uname=:name");
34          *             query.setString(name,"zhangsan");//给name变量赋值
35          * 
36          * 3.模糊查询
37          *             Query query = session.createQuery("from User where uname likt %?%");错!!!!!
38          *             Query query = session.createQuery("from User where uname like ?");对!!!!
39          *             query.setString(0,"%" +"zhang"+ "%");
40          * 
41          * 4.分页查询
42          *             Query query = session.createQuery("from User where uname='zhangsan'");
43          *             query.setFirstResult(0);从满足条件的数据中的第一条数据开始抓取
44          *             query.setMaxResult(2);从满足条件的数据中只抓取前两条数据
45          * 
46          * 5.获取单个对象
47          *             Query query = session.createQuery("select count(*) from User where uname='zhangsan'");
48          *             Object object = query.uniqueResult();
49          * 
50          * 6.构造查询
51          *             Query query = session.createQuery("select new User(5,"zhangsan") from User where uname='zhangsan'");
52          *             Object object = query.uniqueResult();
53          * */
54         
55         /*数据库更新和删除操作executeUpdate()
56          * 1.删除
57          *             Query query = session.createQuery("delete from User where uid in(1,6)");//删除id为1和6的数据,即使数据库中没有符合条件的数据也不会报错
58          *             int execute = query.executeUpdate();//返回成功操作的次数
59          * */
60         
61         //第三步:Query获取结果集
62         //1.list()获取
63         List<?> list = query.list();
64         for(Object u:list){
65             User user = (User)u;
66             System.out.println(user);
67         }
68         /*2.iterate()获取
69          * Iterator<?> iterator = query.iterate();
70          * while(iterator.hasNext()){
71          *        User user = (User)iterator.next();
72          *        System.out.println(user);
73          * }
74          * */
75         /*面试要考:list()和iterate()获取结果集的区别:
76          * list():一次把所有数据从数据库中取出来
77          * iterate():先从数据库中查询满足条件的id,如果缓存中包含全部要查询的id的数据,就无需再查数据库,直接从缓存中取数据,否则,根据id从数据库中取
78          * */
79         
80         //第四步:记得将Session关闭
81         session.close();
82     }
83 }

六、Hibernate的三个状态

    对象(持久化类的实例)处于session对象的管理中才能与数据库发生联系。在Hibernate框架应用中,我们依据对象对象与session对象的关系不同情况,

  把对象的状态分为人的三种:瞬时状态、游离状态、持久状态。

    Transient(瞬时状态|临时状态):在new之后,save()之前,数据库没有应用的数据

      如果对象未与session对象关联过,我们称该对象处于瞬时状态

    Persistent(持久状态):在save()之后,在session关闭之前,数据库有相对应的数据

      如果对象与session关联起来了,且该对象对应到数据库记录,则称该对象处于持久状态

    

  三状态结构图:

          

  三状态转换关系:

      1.瞬时状态转换为持久状态:

          使用session的save()或saveOrUpdate()方法保存对象后,该对象的状态由瞬时状态转换为持久状态

          使用session的get()或load()方法获取对象后,该对象的状态为持久状态

      2.持久状态转换为瞬时状态

          执行session对象的delete()方法后,对象由原来的持久状态变为瞬时状态,因此该对象没有与任何的数据库数据有关联

      3.持久状态变为游离状态

          执行session对象的evict()、clear()、close()方法,对象由原来的持久状态变为游离状态。

      4.游离状态变为持久状态

          重新获取对象session对象,执行session对象的update()或saveOrUpdate方法,由游离状态转换为持久状态,该对象再次与session关联

      5.游离状态转换为瞬时状态

          执行session的delete()方法,对象有游离状态变为瞬时状态

          对瞬时状态或游离状态的对象不再被其他对象引用时,会被Java虚拟机按照垃圾回收机制处理

七、Hibernate根据实体自动构建生成表

  第一步:在hibernate.cfg.xml中添加<property name="hibernate.hbm2ddl.auto">update</property>,设置自动生成表

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7 
 8 <session-factory>
 9     <!--hibernate 方言 区分身份 -->
10     <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
11     <!-- 数据库连接信息 -->
12     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
13     <property name="connection.url">jdbc:mysql://127.0.0.1:3306/hibernatetest</property>
14     <property name="connection.username">root</property>
15     <property name="connection.password">root</property>
16 
17     <!-- hibernate自动生成表 update:如果数据库不存在这张表自动创建一张表,如果存在不创建-->
18     <property name="hibernate.hbm2ddl.auto">update</property>
19     <!-- hibernate在控制台显示SQL语句 -->
20     <property name="show_sql">true</property>
21     <!-- hibernate格式化SQL,控制台看起来更整齐 -->
22     <property name="format_sql">true</property>
23     <!-- 设置自动提交 -->
24     <property name="connection.autocommit">true</property>
25 
26     <!-- <property name="connection.characterEncoding">UTF-8</property> -->
27     <!--加载hibernate映射  -->
28     <mapping resource="com/hibernatetest/entity/Entity.hbm.xml" />
29 </session-factory>
30 
31 </hibernate-configuration>

  第二步:编写实体类

  第三步:配置映射文件

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <!-- name:对应的实体类的权限定名称,table:对应数据库表名称 -->
 6  <class name="com.hibernatetest.entity.Entity" table="hibernateEntity">
 7      <!-- id标签用于配置主键属性
 8              name属性:对应实体类中属性名称
 9              type属性:可以省略,如果省略默认实体类中属性的对应类型
10       -->
11   <id name="userid" type="java.lang.Integer">
12           <!-- column用于设置对应数据库表中字段名。不写column标签,数据库中的字段名则和Entity类中的属性名一致
13               name:数据库表中的字段名
14               length:设置字段长度
15            -->
16           <column name="userid"></column>
17           <!-- generator用于设置主键生成策略
18                native:数据库本地生成策略,适用于多个数据库
19                sequence:序列(Oracle使用)
20                imcrement:主要mysql数据库使用,适用于所有数据库,先查询出最大的id,在此基础上+1,有可能出现并发的问题
21                uuid:生成32位,不会重复的主键,可以达到真正的跨数据库
22                foreign:通常在一对一关联的时候使用
23                自增长:identity,适用于mysql,db2,sql server。
24            -->
25           <generator class="native"></generator>
26   </id>
27   
28   <!-- property标签用于配置其他属性
29              name:对应实体类中属性名称
30              type:可以省略,如果省略默认实体类中属性的对应类型
31       -->
32   <property name="username" type="java.lang.String">
33            <column name="username" length="32"></column>
34   </property>
35   <property name="password" type="java.lang.String" >
36            <column name="password" length="32"></column>
37   </property>
38   
39  </class>
40  
41 </hibernate-mapping>

  第四步:编写测试类测试

    控制台显示hibernate在数据库没找到hibernateEntity表

          

    于是它便会在数据库自动生成一张表

          

八、Hibernate的关联映射

     实体与实体之间有一对一、多对一、多对多的关系,Hibernate也因此需要对表与表之间进行关联映射配置。

     假设:有一张表为Entity,表中有userid,username,password三个字段,另一张表Grade,表中有gradeid,userid,grade。

     我现在通过userid查询对应另一张表中的grade(此处可以理解为多对一)。步骤如下:

      第一步:搭建Hibernate,配置hibernate.cfg.xml,此处由于我们有两张表,所以需要加载两个映射文件

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 
 6 <hibernate-configuration>
 7 
 8 <session-factory>
 9     <!--hibernate 方言 区分身份 -->
10     <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
11     <!-- 数据库连接信息 -->
12     <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
13     <property name="connection.url">jdbc:mysql://127.0.0.1:3306/hibernatetest</property>
14     <property name="connection.username">root</property>
15     <property name="connection.password">root</property>
16 
17     <!-- hibernate自动生成表 update:如果数据库不存在这张表自动创建一张表,如果存在不创建-->
18     <property name="hibernate.hbm2ddl.auto">update</property>
19     <!-- hibernate在控制台显示SQL语句 -->
20     <property name="show_sql">true</property>
21     <!-- hibernate格式化SQL,控制台看起来更整齐 -->
22     <property name="format_sql">true</property>
23     <!-- 设置自动提交 -->
24     <property name="connection.autocommit">true</property>
25 
26     <!-- <property name="connection.characterEncoding">UTF-8</property> -->
27     
28     <!--加载hibernate映射文件  -->
29     <mapping resource="com/hibernatetest/entity/Entity.hbm.xml" />
30     <mapping resource="com/hibernate/grade/Grade.hbm.xml" />
31 </session-factory>
32 
33 </hibernate-configuration>

     第二步:配置两张表对应的映射文件

Entity.hbm.xml:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <!-- name:对应的实体类的权限定名称,table:对应数据库表名称 -->
 6  <class name="com.hibernatetest.entity.Entity" table="hibernateEntity">
 7      <!-- id标签用于配置主键属性
 8              name属性:对应实体类中属性名称
 9              type属性:可以省略,如果省略默认实体类中属性的对应类型
10       -->
11   <id name="userid" type="java.lang.Integer">
12           <!-- column用于设置对应数据库表中字段名。不写column标签,数据库中的字段名则和Entity类中的属性名一致
13               name:数据库表中的字段名
14               length:设置字段长度
15            -->
16           <column name="userid"></column>
17           <!-- generator用于设置主键生成策略
18                native:数据库本地生成策略,适用于多个数据库
19                sequence:序列(Oracle使用)
20                imcrement:主要mysql数据库使用,适用于所有数据库,先查询出最大的id,在此基础上+1,有可能出现并发的问题
21                uuid:生成32位,不会重复的主键,可以达到真正的跨数据库
22                foreign:通常在一对一关联的时候使用
23                自增长:identity,适用于mysql,db2,sql server。
24            -->
25           <generator class="native"></generator>
26   </id>
27   
28   <!-- property标签用于配置其他属性
29              name:对应实体类中属性名称
30              type:可以省略,如果省略默认实体类中属性的对应类型
31       -->
32   <property name="username" type="java.lang.String">
33            <column name="username" length="32"></column>
34   </property>
35   <property name="password" type="java.lang.String" >
36            <column name="password" length="32"></column>
37   </property>
38  </class>
39  
40 </hibernate-mapping>

Grade.hbm.xml:(此处需要加入对grade表的多对一的映射关系)

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5     <!-- name:对应的实体类的权限定名称,table:对应数据库表名称 -->
 6  <class name="com.hibernate.grade.Grade" table="hibernateGrade">
 7      <!-- id标签用于配置主键属性
 8              name属性:对应实体类中属性名称
 9              type属性:可以省略,如果省略默认实体类中属性的对应类型
10       -->
11   <id name="gradeid" type="java.lang.Integer">
12           <!-- column用于设置对应数据库表中字段名。不写column标签,数据库中的字段名则和Entity类中的属性名一致
13               name:数据库表中的字段名
14               length:设置字段长度
15            -->
16           <column name="gradeid"></column>
17           <!-- generator用于设置主键生成策略
18                native:数据库本地生成策略,适用于多个数据库
19                sequence:序列(Oracle使用)
20                imcrement:主要mysql数据库使用,适用于所有数据库,先查询出最大的id,在此基础上+1,有可能出现并发的问题
21                uuid:生成32位,不会重复的主键,可以达到真正的跨数据库
22                foreign:通常在一对一关联的时候使用
23                自增长:identity,适用于mysql,db2,sql server。
24            -->
25           <generator class="native"></generator>
26   </id>
27   
28   <!-- property标签用于配置其他属性
29              name:对应实体类中属性名称
30              type:可以省略,如果省略默认实体类中属性的对应类型
31       -->
32       
33   <!-- 多对一映射关系 -->
34   <!-- name:当前Grade类的Entity属性
35          column:Grade类的外键
36          fetch:有join和select.默认为select
37                   select:查了当前表之后,再查外键所在的那张表
38                   join:在多对一将原本需要两条sql语句以left outer join(左外连接)方式用一条语句解决
39          cascade:级联操作关联表:慎用
40                  save-update:在添加或操作的时候使用级联操作关联表
41                  delete:在删除的时候使用级联操作关联表
42                  all:在所有操作的时候使用级联操作关联表
43                  none:任何时候都不使用
44    -->
45   <many-to-one name="entity" column="userid" fetch="join"></many-to-one>
46   
47   <property name="grade" type="java.lang.Double" >
48            <column name="grade"></column>
49   </property>
50  </class>
51  
52 </hibernate-mapping>

      第三步:编写两张表对应的实体类

Entity类:

 1 package com.hibernatetest.entity;
 2 
 3 public class Entity {
 4     private Integer userid;
 5     private String username;
 6     private String password;
 7     public Entity() {
 8         super();
 9         // TODO Auto-generated constructor stub
10     }
11     public Entity(Integer userid, String username, String password) {
12         super();
13         this.userid = userid;
14         this.username = username;
15         this.password = password;
16     }
17     public Integer getUserid() {
18         return userid;
19     }
20     public void setUserid(Integer userid) {
21         this.userid = userid;
22     }
23     public String getUsername() {
24         return username;
25     }
26     public void setUsername(String username) {
27         this.username = username;
28     }
29     public String getPassword() {
30         return password;
31     }
32     public void setPassword(String password) {
33         this.password = password;
34     }
35     @Override
36     public int hashCode() {
37         final int prime = 31;
38         int result = 1;
39         result = prime * result
40                 + ((password == null) ? 0 : password.hashCode());
41         result = prime * result + ((userid == null) ? 0 : userid.hashCode());
42         result = prime * result
43                 + ((username == null) ? 0 : username.hashCode());
44         return result;
45     }
46     @Override
47     public boolean equals(Object obj) {
48         if (this == obj)
49             return true;
50         if (obj == null)
51             return false;
52         if (getClass() != obj.getClass())
53             return false;
54         Entity other = (Entity) obj;
55         if (password == null) {
56             if (other.password != null)
57                 return false;
58         } else if (!password.equals(other.password))
59             return false;
60         if (userid == null) {
61             if (other.userid != null)
62                 return false;
63         } else if (!userid.equals(other.userid))
64             return false;
65         if (username == null) {
66             if (other.username != null)
67                 return false;
68         } else if (!username.equals(other.username))
69             return false;
70         return true;
71     }
72     @Override
73     public String toString() {
74         return "Entity [userid=" + userid + ", username=" + username
75                 + ", password=" + password + "]";
76     }
77     
78 }

Grade类:

 1 package com.hibernate.grade;
 2 
 3 import com.hibernatetest.entity.Entity;
 4 
 5 public class Grade {
 6     private Integer gradeid;
 7     private Entity entity;
 8     private Double grade;
 9     public Grade() {
10         super();
11         // TODO Auto-generated constructor stub
12     }
13     public Grade(Integer gradeid, Entity entity, Double grade) {
14         super();
15         this.gradeid = gradeid;
16         this.entity = entity;
17         this.grade = grade;
18     }
19     public Integer getGradeid() {
20         return gradeid;
21     }
22     public void setGradeid(Integer gradeid) {
23         this.gradeid = gradeid;
24     }
25     public Entity getEntity() {
26         return entity;
27     }
28     public void setEntity(Entity entity) {
29         this.entity = entity;
30     }
31     public Double getGrade() {
32         return grade;
33     }
34     public void setGrade(Double grade) {
35         this.grade = grade;
36     }
37     @Override
38     public int hashCode() {
39         final int prime = 31;
40         int result = 1;
41         result = prime * result + ((entity == null) ? 0 : entity.hashCode());
42         result = prime * result + ((grade == null) ? 0 : grade.hashCode());
43         result = prime * result + ((gradeid == null) ? 0 : gradeid.hashCode());
44         return result;
45     }
46     @Override
47     public boolean equals(Object obj) {
48         if (this == obj)
49             return true;
50         if (obj == null)
51             return false;
52         if (getClass() != obj.getClass())
53             return false;
54         Grade other = (Grade) obj;
55         if (entity == null) {
56             if (other.entity != null)
57                 return false;
58         } else if (!entity.equals(other.entity))
59             return false;
60         if (grade == null) {
61             if (other.grade != null)
62                 return false;
63         } else if (!grade.equals(other.grade))
64             return false;
65         if (gradeid == null) {
66             if (other.gradeid != null)
67                 return false;
68         } else if (!gradeid.equals(other.gradeid))
69             return false;
70         return true;
71     }
72     @Override
73     public String toString() {
74         return "Grade [gradeid=" + gradeid + ", entity=" + entity + ", grade="
75                 + grade + "]";
76     }
77     
78 }

      第四步:编写HibernateUtils工具类和测试类

测试类:

 1 package Hibernatetest; 4 
 5 import org.hibernate.Query;
 6 import org.hibernate.Session;
 7 import org.hibernate.Transaction;
 8 
 9 import com.hibernate.grade.Grade;
10 import com.hibernatetest.entity.Entity;
11 
12 import HibernatenateUtils.hibernateUtils;
13 
14 public class annotationtest {
15     
16     public void test(){
17         
18     }
19     public static void main(String[] args) {
20         Session session = hibernateUtils.getSession();
21         
22         //先制造两条记录在数据库中
23         Transaction transaction = session.beginTransaction();
24         Entity user1 = new Entity(null,"zhangsan","1111");
25         Grade grade1 = new Grade(null,user1,Double.valueOf(85));
26         session.save(user1);
27         session.save(grade1);
28         transaction.commit();
29         
30         transaction = session.beginTransaction();
31         Entity user2 = new Entity(null,"lisi","2222");
32         Grade grade2 = new Grade(null,user2,Double.valueOf(100));
33         session.save(user2);
34         session.save(grade2);
35         transaction.commit();
36         
37         //查询测试
38         Grade grade = session.get(Grade.class,1);
39         System.out.println(grade);
40         session.close();
41     }
42 }

运行结果:

    

 

posted @ 2020-04-22 20:24  我只是一个码农  阅读(295)  评论(0编辑  收藏  举报