zoukankan      html  css  js  c++  java
  • Hibernate(二)——一对多查询

    1. 前言

            本章节我们讨论Hibernate一对多查询的处理。

            在上一章节中(Hibernate(一)——入门),我们探讨了Hibernate执行最基本的增删改查操作。现在我们将情况复杂化:加入我们在查询用户信息的时候需要同时查询其登录日志,这样就涉及到一对多查询。那么一对多查询要怎么实现么?

    2. jar包准备

            在本节中,除了上一章节中用到的jar包,我还需要用log4j.jar来将Hibernate的查询语句输出到控制台。log4j.properties的配置如下:

      1 log4j.rootLogger=info,console
      2 log4j.appender.console=org.apache.log4j.ConsoleAppender
      3 log4j.appender.console.layout=org.apache.log4j.PatternLayout
      4 log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n

            log4j的使用方法可查阅:Mybatis之一级缓存(七)中,log4j的学习和使用部分。

    3. 数据库准备

            我们需要新建立日志表tbLog,并产生部分的测试数据。代码如下:

    1 CREATE TABLE tbLog (
    2     logID VARCHAR(50),
    3     userID VARCHAR(50),
    4     loginDate DATETIME
    5 )
      1 TRUNCATE TABLE tbUser
      2 TRUNCATE TABLE tbLog
      3 
      4 DECLARE @userID1 VARCHAR(50)
      5 DECLARE @userID2 VARCHAR(50)
      6 SET @userID1 = NEWID();
      7 SET @userID2 = NEWID();
      8 
      9 INSERT INTO tbUser(userID, loginName, userName, passWord)
     10 SELECT @userID1,'luych','卢艳超','12333' UNION ALL
     11 SELECT @userID2,'guest','游客','12333'
     12 
     13 INSERT INTO tbLog(logID, userID, loginDate)
     14 SELECT NEWID(), @userID1, '2016-04-01' UNION ALL
     15 SELECT NEWID(), @userID1, '2016-04-02' UNION ALL
     16 SELECT NEWID(), @userID1, '2016-04-05' UNION ALL
     17 SELECT NEWID(), @userID1, '2016-04-08' UNION ALL
     18 
     19 SELECT NEWID(), @userID2, '2016-04-11' UNION ALL
     20 SELECT NEWID(), @userID2, '2016-04-22'
     21 
     22 SELECT * FROM tbUser;
     23 SELECT * FROM tbLog;

    4. 准备JAVA对象

            (1)建立与数据表tbLog相对应的JAVA对象,代码如下:

      1 package com.luych.hibernate.study.entity;
      2 
      3 import java.util.Date;
      4 
      5 import javax.persistence.Entity;
      6 import javax.persistence.Id;
      7 import javax.persistence.Table;
      8 
      9 
     10 @Entity
     11 @Table(name="tbLog")
     12 public class LogEntity {
     13 
     14     @Id
     15     private String logID;
     16     private String userID;
     17     private Date loginDate;
     18 
     19     public String getLogID() {
     20         return logID;
     21     }
     22     public void setLogID(String logID) {
     23         this.logID = logID;
     24     }
     25     public String getUserID() {
     26         return userID;
     27     }
     28     public void setUserID(String userID) {
     29         this.userID = userID;
     30     }
     31     public Date getLoginDate() {
     32         return loginDate;
     33     }
     34     public void setLoginDate(Date loginDate) {
     35         this.loginDate = loginDate;
     36     }
     37 
     38 
     39 
     40 }

            当然,我们同时也要在Hibernate的xml中增加相应的配置

      1 <mapping class="com.luych.hibernate.study.entity.LogEntity"/>

            (2)调整UserEntity对象,建立其与LogEntity的一对多关系。

      1 package com.luych.hibernate.study.entity;
      2 
      3 import java.text.SimpleDateFormat;
      4 import java.util.Set;
      5 
      6 import javax.persistence.CascadeType;
      7 import javax.persistence.Entity;
      8 import javax.persistence.Id;
      9 import javax.persistence.JoinColumn;
     10 import javax.persistence.OneToMany;
     11 import javax.persistence.Table;
     12 
     13 @Entity
     14 @Table(name="tbUser")
     15 public class UserEntity {
     16 
     17     @Id
     18     private String userID;
     19     private String loginName;
     20     private String userName;
     21     private String passWord;
     22     @OneToMany(cascade=CascadeType.ALL)
     23     @JoinColumn(name="userID")
     24     private Set<LogEntity> logs;
     25 
     26     public String getUserID() {
     27         return userID;
     28     }
     29     public void setUserID(String userID) {
     30         this.userID = userID;
     31     }
     32     public String getLoginName() {
     33         return loginName;
     34     }
     35     public void setLoginName(String loginName) {
     36         this.loginName = loginName;
     37     }
     38     public String getUserName() {
     39         return userName;
     40     }
     41     public void setUserName(String userName) {
     42         this.userName = userName;
     43     }
     44     public String getPassWord() {
     45         return passWord;
     46     }
     47     public void setPassWord(String passWord) {
     48         this.passWord = passWord;
     49     }
     50     public Set<LogEntity> getLogs() {
     51         return logs;
     52     }
     53     public void setLogs(Set<LogEntity> logs) {
     54         this.logs = logs;
     55     }
     56     @Override
     57     public String toString() {
     58         String str = loginName+", "+userName+", "+passWord+", "+userID+" 登录日志:
    ";
     59         for (LogEntity log: logs) {
     60             str = str+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(log.getLoginDate())+"
    ";
     61         }
     62         return str;
     63     }
     64 }
     65 

            其中,

      • @OneToMany的cascade可取值为:
        CascadeType.PERSIST:级联新建,本例中即生成User的时候同时生成Log。
        CascadeType.REMOVE : 级联删除,本例中即删除User的时候同时删除Log。
        CascadeType.REFRESH:级联刷新,本例中即查询User的时候同时查询Log。
        CascadeType.MERGE  :级联更新,本例中即修改User的时候同时修改Log。
        CascadeType.ALL    :以上全部四项,即上面四个全都执行。 
      • @JoinColumn的name取值为:LogEntity中的userID属性。

     

    5. 调整Hibernate配置文件

      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <!DOCTYPE hibernate-configuration PUBLIC
      3         "-//Hibernate/Hibernate Configuration DTD 5.0//EN"
      4         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
      5 <hibernate-configuration>
      6     <session-factory>
      7         <!-- 设置数据库驱动 -->
      8         <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
      9         <!-- 设置数据库URL -->
     10         <property name="hibernate.connection.url">jdbc:sqlserver://192.168.9.23:14433;databaseName=tempdb</property>
     11         <!-- 数据库用户名 -->
     12         <property name="hibernate.connection.username">sa</property>
     13         <!-- 数据库密码 -->
     14         <property name="hibernate.connection.password">123@abcd</property>
     15         <!-- 打印sql -->
     16         <property name="show_sql">true</property>
     17         <property name="format_sql">false</property>
     18         <!-- beans -->
     19         <mapping class="com.luych.hibernate.study.entity.UserEntity"/>
     20         <mapping class="com.luych.hibernate.study.entity.LogEntity"/>
     21     </session-factory>
     22 </hibernate-configuration>

            我们增加了针对show_sql和format_sql的配置,加上这两个配置后,Hibernate会输出执行的SQL脚本。

      • show_sql:true,输出SQL脚本。false,不输出。
      • format_sql:true,格式化SQL脚本。false,不格式化。

            本例中,并没有将format_sql设置为true,是因为格式化的SQL在控制台中显示很占篇幅,不利于我们后面看测试结果,所以关闭了。

    6. 测试运行结果

      1 package com.luych.hibernate.study.main;
      2 
      3 import java.util.Date;
      4 import java.util.HashSet;
      5 import java.util.List;
      6 import java.util.Set;
      7 import java.util.UUID;
      8 
      9 import org.hibernate.Query;
     10 import org.hibernate.Session;
     11 import org.hibernate.SessionFactory;
     12 import org.hibernate.cfg.Configuration;
     13 import org.junit.After;
     14 import org.junit.Before;
     15 import org.junit.Test;
     16 
     17 import com.luych.hibernate.study.entity.LogEntity;
     18 import com.luych.hibernate.study.entity.UserEntity;
     19 
     20 @SuppressWarnings("unchecked")
     21 public class TestMain {
     22 
     23     private Session session;
     24 
     25     @Before
     26     public void getSession(){
     27         Configuration config = new Configuration().configure("hibernate-config.xml");
     28         SessionFactory sessionFactory = config.buildSessionFactory();
     29         session = sessionFactory.openSession();
     30     }
     31 
     32     @After
     33     public void freeSession(){
     34         session.close();
     35     }
     36 
     37     public void sel() {
     38         Query query = session.createQuery("FROM UserEntity WHERE 1=1");
     39         List<UserEntity> userList = query.list();
     40         for (UserEntity userEntity : userList) {
     41             System.out.println(userEntity.toString());
     42         }
     43     }
     44 
     45     public void add() {
     46         session.beginTransaction();
     47         String userID = UUID.randomUUID().toString();
     48         UserEntity user  = new UserEntity();
     49         user.setLoginName("admin");
     50         user.setUserName("系统管理员");
     51         user.setPassWord("12333");
     52         user.setUserID(userID);
     53         LogEntity log1 = new LogEntity();
     54         log1.setLogID(UUID.randomUUID().toString());
     55         log1.setUserID(userID);
     56         log1.setLoginDate(new Date());
     57         LogEntity log2 = new LogEntity();
     58         log2.setLogID(UUID.randomUUID().toString());
     59         log2.setUserID(userID);
     60         log2.setLoginDate(new Date());
     61         Set<LogEntity> logs = new HashSet<LogEntity>();
     62         logs.add(log1);
     63         logs.add(log2);
     64         user.setLogs(logs);
     65         session.save(user);
     66         session.getTransaction().commit();
     67     }
     68 
     69     public void edt(){
     70         session.beginTransaction();
     71         Query query = session.createQuery("FROM UserEntity WHERE 1=1");
     72         List<UserEntity> userList = query.list();
     73         for (UserEntity userEntity : userList) {
     74             userEntity.setPassWord("45666");
     75             LogEntity log = new LogEntity();
     76             log.setLogID(UUID.randomUUID().toString());
     77             log.setUserID(userEntity.getUserID());
     78             log.setLoginDate(new Date());
     79             userEntity.getLogs().add(log);
     80             session.update(userEntity);
     81         }
     82         session.getTransaction().commit();
     83     }
     84 
     85     public void del(){
     86         session.beginTransaction();
     87         Query query = session.createQuery("FROM UserEntity WHERE 1=1");
     88         List<UserEntity> userList = query.list();
     89         for (UserEntity userEntity : userList) {
     90             session.delete(userEntity);
     91         }
     92         session.getTransaction().commit();
     93     }
     94 
     95     @Test
     96     public void test(){
     97         System.out.println("
    ----------现有用户:");
     98         sel();
     99         System.out.println("
    ----------开始增加用户:");
    100         add();
    101         System.out.println("
    ----------增加用户后:");
    102         sel();
    103         System.out.println("
    ----------开始修改用户:");
    104         edt();
    105         System.out.println("
    ----------修改用户后:");
    106         sel();
    107         System.out.println("
    ----------开始删除用户:");
    108         del();
    109         System.out.println("
    ----------删除用户后:");
    110         sel();
    111     }
    112 }

            getSession和freeSession和上一章节中相同,不再赘述。

            add方法,新建了一个用户并设定了两条登录日志,然后保存。edt方法,将所有用户的密码改为45666,并为所有的用户增加一条登录日志。del方法,删除所有的用户。sel方法,查询所有用户信息并输出到控制台。

            右键,Run As JUnit Test后,控制台输出结果为:

      1 
      2 ----------现有用户:
      3 Hibernate: select userentity0_.userID as userID1_1_, userentity0_.loginName as loginNam2_1_, 
                          userentity0_.passWord as passWord3_1_, userentity0_.userName as userName4_1_ 
                   from tbUser userentity0_ where 1=1
      4 Hibernate: select logs0_.userID as userID3_0_0_, logs0_.logID as logID1_0_0_, 
                          logs0_.logID as logID1_0_1_, logs0_.loginDate as loginDat2_0_1_, logs0_.userID as userID3_0_1_ 
                   from tbLog logs0_ where logs0_.userID=?
      5 
      6 luych, 卢艳超, 12333, CB6172E3-8750-4718-BEF6-EE0917015FA9 登录日志:
      7 2016-04-01 00:00:00
      8 2016-04-08 00:00:00
      9 2016-04-05 00:00:00
     10 2016-04-02 00:00:00
     11 
     12 Hibernate: select logs0_.userID as userID3_0_0_, logs0_.logID as logID1_0_0_, 
                          logs0_.logID as logID1_0_1_, logs0_.loginDate as loginDat2_0_1_, logs0_.userID as userID3_0_1_ 
                   from tbLog logs0_ where logs0_.userID=?
     13 
     14 guest, 游客, 12333, 21539577-A3D1-4A1F-8D10-6ED0540A46A0 登录日志:
     15 2016-04-11 00:00:00
     16 2016-04-22 00:00:00
     17 
     18 
     19 ----------开始增加用户:
     20 Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_, logentity_.userID as userID3_0_ 
                   from tbLog logentity_ where logentity_.logID=?
     21 Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_, logentity_.userID as userID3_0_ 
                   from tbLog logentity_ where logentity_.logID=?
     22 Hibernate: insert into tbUser (loginName, passWord, userName, userID) values (?, ?, ?, ?)
     23 Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
     24 Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
     25 Hibernate: update tbLog set userID=? where logID=?
     26 Hibernate: update tbLog set userID=? where logID=?
     27 
     28 ----------增加用户后:
     29 Hibernate: select userentity0_.userID as userID1_1_, userentity0_.loginName as loginNam2_1_, 
                          userentity0_.passWord as passWord3_1_, userentity0_.userName as userName4_1_ 
                   from tbUser userentity0_ where 1=1
     30 
     31 luych, 卢艳超, 12333, CB6172E3-8750-4718-BEF6-EE0917015FA9 登录日志:
     32 2016-04-01 00:00:00
     33 2016-04-08 00:00:00
     34 2016-04-05 00:00:00
     35 2016-04-02 00:00:00
     36 
     37 
     38 guest, 游客, 12333, 21539577-A3D1-4A1F-8D10-6ED0540A46A0 登录日志:
     39 2016-04-11 00:00:00
     40 2016-04-22 00:00:00
     41 
     42 
     43 admin, 系统管理员, 12333, 99d5d264-9d02-4e45-a8c5-f710cc14107e 登录日志:
     44 2016-04-26 17:06:00
     45 2016-04-26 17:06:00
     46 
     47 
     48 ----------开始修改用户:
     49 Hibernate: select userentity0_.userID as userID1_1_, userentity0_.loginName as loginNam2_1_, 
                          userentity0_.passWord as passWord3_1_, userentity0_.userName as userName4_1_ 
                   from tbUser userentity0_ where 1=1
     50 Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_, 
                          logentity_.userID as userID3_0_ 
                   from tbLog logentity_ where logentity_.logID=?
     51 Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_, 
                          logentity_.userID as userID3_0_ 
                   from tbLog logentity_ where logentity_.logID=?
     52 Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_, 
                          logentity_.userID as userID3_0_ 
                   from tbLog logentity_ where logentity_.logID=?
     53 Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
     54 Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
     55 Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
     56 Hibernate: update tbUser set loginName=?, passWord=?, userName=? where userID=?
     57 Hibernate: update tbUser set loginName=?, passWord=?, userName=? where userID=?
     58 Hibernate: update tbUser set loginName=?, passWord=?, userName=? where userID=?
     59 Hibernate: update tbLog set userID=? where logID=?
     60 Hibernate: update tbLog set userID=? where logID=?
     61 Hibernate: update tbLog set userID=? where logID=?
     62 
     63 ----------修改用户后:
     64 Hibernate: select userentity0_.userID as userID1_1_, userentity0_.loginName as loginNam2_1_, 
                          userentity0_.passWord as passWord3_1_, userentity0_.userName as userName4_1_ 
                   from tbUser userentity0_ where 1=1
     65 
     66 luych, 卢艳超, 45666, CB6172E3-8750-4718-BEF6-EE0917015FA9 登录日志:
     67 2016-04-01 00:00:00
     68 2016-04-08 00:00:00
     69 2016-04-05 00:00:00
     70 2016-04-02 00:00:00
     71 2016-04-26 17:06:00
     72 
     73 
     74 guest, 游客, 45666, 21539577-A3D1-4A1F-8D10-6ED0540A46A0 登录日志:
     75 2016-04-11 00:00:00
     76 2016-04-22 00:00:00
     77 2016-04-26 17:06:00
     78 
     79 
     80 admin, 系统管理员, 45666, 99d5d264-9d02-4e45-a8c5-f710cc14107e 登录日志:
     81 2016-04-26 17:06:00
     82 2016-04-26 17:06:00
     83 2016-04-26 17:06:00
     84 
     85 
     86 ----------开始删除用户:
     87 Hibernate: select userentity0_.userID as userID1_1_, userentity0_.loginName as loginNam2_1_, 
                          userentity0_.passWord as passWord3_1_, userentity0_.userName as userName4_1_ 
                   from tbUser userentity0_ where 1=1
     88 Hibernate: update tbLog set userID=null where userID=?
     89 Hibernate: update tbLog set userID=null where userID=?
     90 Hibernate: update tbLog set userID=null where userID=?
     91 Hibernate: delete from tbLog where logID=?
     92 Hibernate: delete from tbLog where logID=?
     93 Hibernate: delete from tbLog where logID=?
     94 Hibernate: delete from tbLog where logID=?
     95 Hibernate: delete from tbLog where logID=?
     96 Hibernate: delete from tbUser where userID=?
     97 Hibernate: delete from tbLog where logID=?
     98 Hibernate: delete from tbLog where logID=?
     99 Hibernate: delete from tbLog where logID=?
    100 Hibernate: delete from tbUser where userID=?
    101 Hibernate: delete from tbLog where logID=?
    102 Hibernate: delete from tbLog where logID=?
    103 Hibernate: delete from tbLog where logID=?
    104 Hibernate: delete from tbUser where userID=?
    105 
    106 ----------删除用户后:
    107 Hibernate: select userentity0_.userID as userID1_1_, userentity0_.loginName as loginNam2_1_, 
                          userentity0_.passWord as passWord3_1_, userentity0_.userName as userName4_1_ 
                   from tbUser userentity0_ where 1=1
    108 

            从打印结果中,我们可以看到,新增、编辑、删除用户信息的时候,Hibernate都帮我们完成登录日志的新增、删除、操作。查询的时候也如此。

            但是需要提点的是:在Hibernate第一次查询中,我们看到它先查询了tbUser表,然后针对tbUser表的每一个记录都又查询了下tbLog表,这就是经典的N+1查询问题,所以效率嘛…

            以上就是Hibernate中一对多的查询关联,其他关联情况将在后续的博文中讲解。

    笔者只是初学者,开此博客的初衷是为了给自己的学习过程留一个痕迹。所以您可能发现笔者措辞不严谨、逻辑不合理,甚至代码有错误、结论很偏颇等等。笔者感激各位的讨论和指正,并在此不胜感激!拜谢!欢迎加QQ群讨论:852410026
  • 相关阅读:
    JS变量的作用域
    使用jquery修改css中带有!important的样式属性
    js异步加载的三种解决方案
    js 停止事件冒泡 阻止浏览器的默认行为(阻止超连接 # )
    【翻译】MongoDB指南/CRUD操作(二)
    【翻译】MongoDB指南/CRUD操作(一)
    【翻译】MongoDB指南/引言
    深入浅出UML类图(一)
    让thinkphp 5 支持pathinfo 的 nginx ,去掉index.php
    linux 常用命令
  • 原文地址:https://www.cnblogs.com/LOVE0612/p/5435886.html
Copyright © 2011-2022 走看看