Hibernate(二)——一对多查询
1. 前言
本章节我们讨论Hibernate一对多查询的处理。
在上一章节中(Hibernate(一)——入门),我们探讨了Hibernate执行最基本的增删改查操作。现在我们将情况复杂化:加入我们在查询用户信息的时候需要同时查询其登录日志,这样就涉及到一对多查询。那么一对多查询要怎么实现么?
2. jar包准备
在本节中,除了上一章节中用到的jar包,我还需要用log4j.jar来将Hibernate的查询语句输出到控制台。log4j.properties的配置如下:
log4j.rootLogger=info,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n
log4j的使用方法可查阅:Mybatis之一级缓存(七)中,log4j的学习和使用部分。
3. 数据库准备
我们需要新建立日志表tbLog,并产生部分的测试数据。代码如下:
CREATE TABLE tbLog (
logID VARCHAR(50),
userID VARCHAR(50),
loginDate DATETIME
)
TRUNCATE TABLE tbUser
TRUNCATE TABLE tbLog DECLARE @userID1 VARCHAR(50)
DECLARE @userID2 VARCHAR(50)
SET @userID1 = NEWID();
SET @userID2 = NEWID(); INSERT INTO tbUser(userID, loginName, userName, passWord)
SELECT @userID1,'luych','卢艳超','' UNION ALL
SELECT @userID2,'guest','游客','' INSERT INTO tbLog(logID, userID, loginDate)
SELECT NEWID(), @userID1, '2016-04-01' UNION ALL
SELECT NEWID(), @userID1, '2016-04-02' UNION ALL
SELECT NEWID(), @userID1, '2016-04-05' UNION ALL
SELECT NEWID(), @userID1, '2016-04-08' UNION ALL SELECT NEWID(), @userID2, '2016-04-11' UNION ALL
SELECT NEWID(), @userID2, '2016-04-22' SELECT * FROM tbUser;
SELECT * FROM tbLog;
4. 准备JAVA对象
(1)建立与数据表tbLog相对应的JAVA对象,代码如下:
package com.luych.hibernate.study.entity; import java.util.Date; import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table; @Entity
@Table(name="tbLog")
public class LogEntity { @Id
private String logID;
private String userID;
private Date loginDate; public String getLogID() {
return logID;
}
public void setLogID(String logID) {
this.logID = logID;
}
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public Date getLoginDate() {
return loginDate;
}
public void setLoginDate(Date loginDate) {
this.loginDate = loginDate;
} }
当然,我们同时也要在Hibernate的xml中增加相应的配置
<mapping class="com.luych.hibernate.study.entity.LogEntity"/>
(2)调整UserEntity对象,建立其与LogEntity的一对多关系。
package com.luych.hibernate.study.entity; import java.text.SimpleDateFormat;
import java.util.Set; import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table; @Entity
@Table(name="tbUser")
public class UserEntity { @Id
private String userID;
private String loginName;
private String userName;
private String passWord;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="userID")
private Set<LogEntity> logs; public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public Set<LogEntity> getLogs() {
return logs;
}
public void setLogs(Set<LogEntity> logs) {
this.logs = logs;
}
@Override
public String toString() {
String str = loginName+", "+userName+", "+passWord+", "+userID+" 登录日志:\n";
for (LogEntity log: logs) {
str = str+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(log.getLoginDate())+"\n";
}
return str;
}
}
其中,
- @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配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 5.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 设置数据库驱动 -->
<property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<!-- 设置数据库URL -->
<property name="hibernate.connection.url">jdbc:sqlserver://192.168.9.23:14433;databaseName=tempdb</property>
<!-- 数据库用户名 -->
<property name="hibernate.connection.username">sa</property>
<!-- 数据库密码 -->
<property name="hibernate.connection.password">123@abcd</property>
<!-- 打印sql -->
<property name="show_sql">true</property>
<property name="format_sql">false</property>
<!-- beans -->
<mapping class="com.luych.hibernate.study.entity.UserEntity"/>
<mapping class="com.luych.hibernate.study.entity.LogEntity"/>
</session-factory>
</hibernate-configuration>
我们增加了针对show_sql和format_sql的配置,加上这两个配置后,Hibernate会输出执行的SQL脚本。
- show_sql:true,输出SQL脚本。false,不输出。
- format_sql:true,格式化SQL脚本。false,不格式化。
本例中,并没有将format_sql设置为true,是因为格式化的SQL在控制台中显示很占篇幅,不利于我们后面看测试结果,所以关闭了。
6. 测试运行结果
package com.luych.hibernate.study.main; import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID; import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import com.luych.hibernate.study.entity.LogEntity;
import com.luych.hibernate.study.entity.UserEntity; @SuppressWarnings("unchecked")
public class TestMain { private Session session; @Before
public void getSession(){
Configuration config = new Configuration().configure("hibernate-config.xml");
SessionFactory sessionFactory = config.buildSessionFactory();
session = sessionFactory.openSession();
} @After
public void freeSession(){
session.close();
} public void sel() {
Query query = session.createQuery("FROM UserEntity WHERE 1=1");
List<UserEntity> userList = query.list();
for (UserEntity userEntity : userList) {
System.out.println(userEntity.toString());
}
} public void add() {
session.beginTransaction();
String userID = UUID.randomUUID().toString();
UserEntity user = new UserEntity();
user.setLoginName("admin");
user.setUserName("系统管理员");
user.setPassWord("");
user.setUserID(userID);
LogEntity log1 = new LogEntity();
log1.setLogID(UUID.randomUUID().toString());
log1.setUserID(userID);
log1.setLoginDate(new Date());
LogEntity log2 = new LogEntity();
log2.setLogID(UUID.randomUUID().toString());
log2.setUserID(userID);
log2.setLoginDate(new Date());
Set<LogEntity> logs = new HashSet<LogEntity>();
logs.add(log1);
logs.add(log2);
user.setLogs(logs);
session.save(user);
session.getTransaction().commit();
} public void edt(){
session.beginTransaction();
Query query = session.createQuery("FROM UserEntity WHERE 1=1");
List<UserEntity> userList = query.list();
for (UserEntity userEntity : userList) {
userEntity.setPassWord("");
LogEntity log = new LogEntity();
log.setLogID(UUID.randomUUID().toString());
log.setUserID(userEntity.getUserID());
log.setLoginDate(new Date());
userEntity.getLogs().add(log);
session.update(userEntity);
}
session.getTransaction().commit();
} public void del(){
session.beginTransaction();
Query query = session.createQuery("FROM UserEntity WHERE 1=1");
List<UserEntity> userList = query.list();
for (UserEntity userEntity : userList) {
session.delete(userEntity);
}
session.getTransaction().commit();
} @Test
public void test(){
System.out.println("\n----------现有用户:");
sel();
System.out.println("\n----------开始增加用户:");
add();
System.out.println("\n----------增加用户后:");
sel();
System.out.println("\n----------开始修改用户:");
edt();
System.out.println("\n----------修改用户后:");
sel();
System.out.println("\n----------开始删除用户:");
del();
System.out.println("\n----------删除用户后:");
sel();
}
}
getSession和freeSession和上一章节中相同,不再赘述。
add方法,新建了一个用户并设定了两条登录日志,然后保存。edt方法,将所有用户的密码改为45666,并为所有的用户增加一条登录日志。del方法,删除所有的用户。sel方法,查询所有用户信息并输出到控制台。
右键,Run As JUnit Test后,控制台输出结果为:
----------现有用户:
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
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=? luych, 卢艳超, 12333, CB6172E3-8750-4718-BEF6-EE0917015FA9 登录日志:
2016-04-01 00:00:00
2016-04-08 00:00:00
2016-04-05 00:00:00
2016-04-02 00:00:00 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=? guest, 游客, 12333, 21539577-A3D1-4A1F-8D10-6ED0540A46A0 登录日志:
2016-04-11 00:00:00
2016-04-22 00:00:00 ----------开始增加用户:
Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_, logentity_.userID as userID3_0_
from tbLog logentity_ where logentity_.logID=?
Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_, logentity_.userID as userID3_0_
from tbLog logentity_ where logentity_.logID=?
Hibernate: insert into tbUser (loginName, passWord, userName, userID) values (?, ?, ?, ?)
Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
Hibernate: update tbLog set userID=? where logID=?
Hibernate: update tbLog set userID=? where logID=? ----------增加用户后:
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 luych, 卢艳超, 12333, CB6172E3-8750-4718-BEF6-EE0917015FA9 登录日志:
2016-04-01 00:00:00
2016-04-08 00:00:00
2016-04-05 00:00:00
2016-04-02 00:00:00 guest, 游客, 12333, 21539577-A3D1-4A1F-8D10-6ED0540A46A0 登录日志:
2016-04-11 00:00:00
2016-04-22 00:00:00 admin, 系统管理员, 12333, 99d5d264-9d02-4e45-a8c5-f710cc14107e 登录日志:
2016-04-26 17:06:00
2016-04-26 17:06:00 ----------开始修改用户:
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
Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_,
logentity_.userID as userID3_0_
from tbLog logentity_ where logentity_.logID=?
Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_,
logentity_.userID as userID3_0_
from tbLog logentity_ where logentity_.logID=?
Hibernate: select logentity_.logID, logentity_.loginDate as loginDat2_0_,
logentity_.userID as userID3_0_
from tbLog logentity_ where logentity_.logID=?
Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
Hibernate: insert into tbLog (loginDate, userID, logID) values (?, ?, ?)
Hibernate: update tbUser set loginName=?, passWord=?, userName=? where userID=?
Hibernate: update tbUser set loginName=?, passWord=?, userName=? where userID=?
Hibernate: update tbUser set loginName=?, passWord=?, userName=? where userID=?
Hibernate: update tbLog set userID=? where logID=?
Hibernate: update tbLog set userID=? where logID=?
Hibernate: update tbLog set userID=? where logID=? ----------修改用户后:
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 luych, 卢艳超, 45666, CB6172E3-8750-4718-BEF6-EE0917015FA9 登录日志:
2016-04-01 00:00:00
2016-04-08 00:00:00
2016-04-05 00:00:00
2016-04-02 00:00:00
2016-04-26 17:06:00 guest, 游客, 45666, 21539577-A3D1-4A1F-8D10-6ED0540A46A0 登录日志:
2016-04-11 00:00:00
2016-04-22 00:00:00
2016-04-26 17:06:00 admin, 系统管理员, 45666, 99d5d264-9d02-4e45-a8c5-f710cc14107e 登录日志:
2016-04-26 17:06:00
2016-04-26 17:06:00
2016-04-26 17:06:00 ----------开始删除用户:
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
Hibernate: update tbLog set userID=null where userID=?
Hibernate: update tbLog set userID=null where userID=?
Hibernate: update tbLog set userID=null where userID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbUser where userID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbUser where userID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbLog where logID=?
Hibernate: delete from tbUser where userID=? ----------删除用户后:
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
从打印结果中,我们可以看到,新增、编辑、删除用户信息的时候,Hibernate都帮我们完成登录日志的新增、删除、操作。查询的时候也如此。
但是需要提点的是:在Hibernate第一次查询中,我们看到它先查询了tbUser表,然后针对tbUser表的每一个记录都又查询了下tbLog表,这就是经典的N+1查询问题,所以效率嘛…
以上就是Hibernate中一对多的查询关联,其他关联情况将在后续的博文中讲解。
Hibernate(二)——一对多查询的更多相关文章
- Hibernate的一对多查询及去掉重复的对象distinct
问:sql 中 select * from A left join B on A.id=B.id where A.id=? 如果在Hibernate 中 用HQL 怎么表达呢 ?答:from A le ...
- hibernate一对多查询
一对多查询 1,同时添加老师和学生案例 在进行具有关联关系的对象同时添加时 首先绑定对像间的关系 ---将多方关联一方 ---将一方关联多方 然后全部添加 备注: 1,保存老师对象时, 由于设置了学生 ...
- Hibernate框架之Criteria查询 和注解(重点☆☆☆☆☆,难点☆☆☆)
写好一篇博客,不是容易的事.原因是:你要给自己以后看的时候,还能看懂,最重要的是当别人看到你的博客文章的时候,也一样很清楚的明白你自己写的东西.其实这也是一种成就感!! 对于每一个知识点,要有必要的解 ...
- Hibernate(二)
性能分析 抓取策略 研究对象 研究怎么样提取集合的,该策略应该作用与set元素上 研究从一的一方加载多的一方 案例 查询cid为1的班级的所有的学生 明:通过一条sql语句:左外链接,把classes ...
- Hibernate-ORM:15.Hibernate中的Criteria查询
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客讲师Hibernate中的Criteria查询! 一,Criteria简介: 刚接触Hibernate ...
- Hibernate-ORM:11.Hibernate中的关联查询
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客将讲述Hibernate中的关联查询,及其级联(cascade)操作,以及指定哪一方维护关联关系的(i ...
- Hibernate框架之Criteria查询
首先给大家说说Hibernate检索方式 Hibernate提供了5种检索对象的方式 1.导航对象图检索方式:根据已经加载的对象导航到其他对象 2.OID检索方式:按照对象的OID来检索对象 3.HQ ...
- hibernate使用原生SQL查询返回结果集的处理
今天没事的时候,看到公司框架里有一个用原生SQL写的函数,说实在以前自己也干过这事,但好久都没有用,都忘得差不多了,现在基本都是用的hql语句来查询结果.hibernate中使用createSQLQu ...
- Mybatis一对多查询得不到多方结果
一对多查询:一个年级对应多个学生,现在要查询年级(带学生)信息. 查询结果: [main] INFO com.java1234.service.GradeTest - 查询年级(带学生)[main] ...
随机推荐
- 图片索引 lire
1:定义 LIRE( Lucene Image Retrieval)相似图像索引和搜索机制 2:资料来源 LIRE官网:http://www.semanticmetadata.net/lir ...
- Oracle 修改 提交后 回退
1. -- 查询你执行update 语句之前的数据 精确到什么时间 select * from 表名 as of timestamp to_timestamp('2017-07-21 17:16:38 ...
- python 数据处理 对txt文件进行数据处理
数据: 对txt文件进行数据处理: txt_file_path = "basic_info.txt" write_txt_file_path = "basic_info1 ...
- android中的简单animation(二)push up,push left,cross fade,hyperspace
animation_2.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- Mongoose使用
文章来自 Mongoose基础入门 Mongoose的API Mongoose模式扩展 指南之查询 指南之验证 mongoose方法很多,很乱,版本不一样,有些方法可能都过时了,所以整理了很久 连接数 ...
- 页面的html调试
点击页面按下键盘的F12,或者鼠标右键选择检查(N) 会弹出一个窗口,这个窗口就是调试窗口 如上图所示,第一个图标是标签元素选择器,点击使用后,在页面上移动,会在Elements的区域找到你鼠标选中的 ...
- Day7 - J - Raising Modulo Numbers POJ - 1995
People are different. Some secretly read magazines full of interesting girls' pictures, others creat ...
- 010-PHP输出数组中第某个元素
<?php $monthName = array(1 => "January", "February", "March",//初 ...
- 指令——cat
作用1:cat有直接打开一个文件的功能,只看不用编辑. 语法:#cat 文件的路径 选项:-n, --number 对输出的所有行编号. 如:用cat查看/etc/passwd [root@local ...
- 八十三、SAP中的ALV创建之二,ALV相关的类型池定义
一.与ALV相关的类型都是在TYPE-POOLS:SLIS中.我们来到SE11 二.常用的定义有fieldca和layout等,用于显示字段,和控制信息数据等. 三.我们以VBAK表为例,用ALV输出 ...