• 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 }

    运行结果:

        

  • 相关阅读:
    敏捷开发原则与实践(一)
    ACM Steps_Chapter Two_Section3
    ACM Steps_Chapter Three_Section3
    ACM Steps_Chapter Three_Section1
    ACM Steps_Chapter Three_Section2
    ACM Steps_Chapter Four_Section1
    java网络编程(2)——UDP与TCP
    java网络编程(1)
    mybatis与spring的整合(使用接口实现crud)
    mybatis与spring的整合(使用sqlSession进行crud)
  • 原文地址:https://www.cnblogs.com/qinqin-me/p/12735397.html
Copyright © 2020-2023  润新知