【Hibernate】Hibernate的多表查询
2017-01-13 16:19
99 查看
在《【hibernate】Hibernate的聚类查询、分组查询、排序与时间之差》(点击打开链接)一文中已经讲述过如何利用HQL语句取代SQL语句,进行聚类查询、分组查询、排序与时间之差的查询,同时指出hql能代替sql语句做任何事情。我原本以为hql语句的多表查询,要先对里面的实体做Java与xml的修改,其实并不需要,同样是一句HQL语句就能搞定的事情。
4000
SQL的多表查询已经在《【MySQL】利用内连接与嵌套查询实现多表查询,主键、外键的基本概念》(点击打开链接)讲过。
比如如下的SQL语句:
[sql] view
plain copy print?
select t1.Title,t1.Content
from blog as t1 ,usertable as t2
where t1.userid=t2.id and t2.username='a'
转换成HQL语句则如下:
[java] view
plain copy print?
String hql="select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'"
List<Object> resultList = session.createQuery(hql).list();
for (int i = 0; i < resultList.size(); i++) {
Object[] obj = (Object[])resultList.get(i);
System.out.println(obj[0]+","+obj[1]);
}
核心思想,是把sql语句中的表,写成Hibernate的实体,sql语句中的字段、列,写成Hibernate的实体的成员变量,同时必须把表使用as进行t1,t2等标记,不能使用Blog.XX字段来简化,如上,就是Blog,Usertable两张表转化为t1,t2标记,把sql的字段、列,表对应转化为Hibernate的实体成员变量,实体进行查询。
Hibernate查询出来的结果是一个存放Object数组的List,也就是说List的每项都是一个Object数组,Object数组的第n项对应查询结果的第n项。
可以再进行下一步的处理。
下面用一个例子,来说明HQL语句的多表查询。
如图,Blog记录了用户发表的博客,usertable记录了用户的基本信息。Blog表中的userid与usertable的主键id形成参照完整性。
这两张表在Hibernate的Java工程种分别对应如下实体:
Blog.java
[java] view
plain copy print?
import javax.persistence.*;
@Entity
@Table(name = "blog")
public class Blog {
private int id;
private String title;
private String content;
private int userId;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "Title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Column(name = "Content")
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Column(name = "userid")
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
@Override
public String toString() {
return id + "," + title + "," + content + "," + userId;
}
}
Usertable.java
[java] view
plain copy print?
import javax.persistence.*;
@Entity
@Table(name = "usertable")
public class Usertable {
private int id;
private String username;
private String password;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return id + "," + username + "," + password;
}
}
同时,hibernate.cfg.xml做如下的配置:
[html] view
plain copy print?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--所用的数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!--所用的数据库登陆密码 -->
<property name="hibernate.connection.password">admin</property>
<!--所用的数据库名称为test,根据实际更改 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
<!--所用的数据库用户名 -->
<property name="hibernate.connection.username">pc</property>
<!--所用的数据库方言,与所用数据库驱动一样,可以在网上查到,这里是mysql -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.format_sql">true</property>
<!--如果是update表明Hibernate将保留原来的数据记录,插入时把新记录添加到已有的表, -->
<!--如果是create,则总是创建新的表,如果原来数据库已有的这个表,则这个表的记录会被全部清洗 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--罗列Testtable表与Java文件的映射 -->
<!--将数据库中的usertable表,blog表映射到Usertable.java与Blog.java两个实体 -->
<mapping class="Usertable" />
<mapping class="Blog" />
</session-factory>
</hibernate-configuration>
可以发现,这没有进行任何的参照完整性的指定。下面,要查询usertable中username为a的用户,发表的Blog。
我们知道先要查询username为a的用户的id,之后利用这个查出来的id到Blog表中查询。
用sql语句完成这个多表查询,则这样写:
[sql] view
plain copy print?
select t1.Title,t1.Content
from blog as t1 ,usertable as t2
where t1.userid=t2.id and t2.username='a'
其查询结果如下:
这使用Hibernate则这样写,在HibernateMultiTableTest.java中的代码如下:
[java] view
plain copy print?
import java.util.List;
import org.hibernate.*;
import org.hibernate.cfg.*;
class dbDAO {
private Session session;
// 构造函数,初始化Session,相当于连接数据库
public dbDAO() {
// new Configuration().configure()是吧hibernate.cfg.xml中的所有配置读取进来
// .buildSessionFactory().openSession()是创建Session工厂并实例化session
this.session = new Configuration().configure().buildSessionFactory()
.openSession();
}
// 执行查询
public Query query(String hql) {
return session.createQuery(hql);
}
// 执行插入、修改
public void save(Object object) {
Transaction transaction = session.beginTransaction();
session.save(object);
transaction.commit();
}
// 执行删除
public void delete(Object object) {
Transaction transaction = session.beginTransaction();
session.delete(object);
transaction.commit();
}
// 析构函数,中断Session,相当于中断数据库的连接
protected void finalize() throws Exception {
if (session.isConnected() || session != null) {
session.close();
}
}
}
@SuppressWarnings("unchecked")
public class HibernateMultiTableTest {
public static void main(String args[]) {
dbDAO db = new dbDAO();
List<Object> resultList = db
.query("select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'")
.list();//HQL的多表查询
System.out.println("usertable中username为a的用户,发表的内容如下:");
System.out.println();
for (int i = 0; i < resultList.size(); i++) {
Object[] obj = (Object[]) resultList.get(i);
System.out.println("标题:" + obj[0]);
System.out.println("内容:" + obj[1]);
System.out.println();
}
}
}
其运行结果如下:
转载自:yongh701
4000
SQL的多表查询已经在《【MySQL】利用内连接与嵌套查询实现多表查询,主键、外键的基本概念》(点击打开链接)讲过。
比如如下的SQL语句:
[sql] view
plain copy print?
select t1.Title,t1.Content
from blog as t1 ,usertable as t2
where t1.userid=t2.id and t2.username='a'
转换成HQL语句则如下:
[java] view
plain copy print?
String hql="select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'"
List<Object> resultList = session.createQuery(hql).list();
for (int i = 0; i < resultList.size(); i++) {
Object[] obj = (Object[])resultList.get(i);
System.out.println(obj[0]+","+obj[1]);
}
核心思想,是把sql语句中的表,写成Hibernate的实体,sql语句中的字段、列,写成Hibernate的实体的成员变量,同时必须把表使用as进行t1,t2等标记,不能使用Blog.XX字段来简化,如上,就是Blog,Usertable两张表转化为t1,t2标记,把sql的字段、列,表对应转化为Hibernate的实体成员变量,实体进行查询。
Hibernate查询出来的结果是一个存放Object数组的List,也就是说List的每项都是一个Object数组,Object数组的第n项对应查询结果的第n项。
可以再进行下一步的处理。
下面用一个例子,来说明HQL语句的多表查询。
如图,Blog记录了用户发表的博客,usertable记录了用户的基本信息。Blog表中的userid与usertable的主键id形成参照完整性。
这两张表在Hibernate的Java工程种分别对应如下实体:
Blog.java
[java] view
plain copy print?
import javax.persistence.*;
@Entity
@Table(name = "blog")
public class Blog {
private int id;
private String title;
private String content;
private int userId;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "Title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Column(name = "Content")
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Column(name = "userid")
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
@Override
public String toString() {
return id + "," + title + "," + content + "," + userId;
}
}
Usertable.java
[java] view
plain copy print?
import javax.persistence.*;
@Entity
@Table(name = "usertable")
public class Usertable {
private int id;
private String username;
private String password;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(name = "username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return id + "," + username + "," + password;
}
}
同时,hibernate.cfg.xml做如下的配置:
[html] view
plain copy print?
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--所用的数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!--所用的数据库登陆密码 -->
<property name="hibernate.connection.password">admin</property>
<!--所用的数据库名称为test,根据实际更改 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
<!--所用的数据库用户名 -->
<property name="hibernate.connection.username">pc</property>
<!--所用的数据库方言,与所用数据库驱动一样,可以在网上查到,这里是mysql -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.format_sql">true</property>
<!--如果是update表明Hibernate将保留原来的数据记录,插入时把新记录添加到已有的表, -->
<!--如果是create,则总是创建新的表,如果原来数据库已有的这个表,则这个表的记录会被全部清洗 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--罗列Testtable表与Java文件的映射 -->
<!--将数据库中的usertable表,blog表映射到Usertable.java与Blog.java两个实体 -->
<mapping class="Usertable" />
<mapping class="Blog" />
</session-factory>
</hibernate-configuration>
可以发现,这没有进行任何的参照完整性的指定。下面,要查询usertable中username为a的用户,发表的Blog。
我们知道先要查询username为a的用户的id,之后利用这个查出来的id到Blog表中查询。
用sql语句完成这个多表查询,则这样写:
[sql] view
plain copy print?
select t1.Title,t1.Content
from blog as t1 ,usertable as t2
where t1.userid=t2.id and t2.username='a'
其查询结果如下:
这使用Hibernate则这样写,在HibernateMultiTableTest.java中的代码如下:
[java] view
plain copy print?
import java.util.List;
import org.hibernate.*;
import org.hibernate.cfg.*;
class dbDAO {
private Session session;
// 构造函数,初始化Session,相当于连接数据库
public dbDAO() {
// new Configuration().configure()是吧hibernate.cfg.xml中的所有配置读取进来
// .buildSessionFactory().openSession()是创建Session工厂并实例化session
this.session = new Configuration().configure().buildSessionFactory()
.openSession();
}
// 执行查询
public Query query(String hql) {
return session.createQuery(hql);
}
// 执行插入、修改
public void save(Object object) {
Transaction transaction = session.beginTransaction();
session.save(object);
transaction.commit();
}
// 执行删除
public void delete(Object object) {
Transaction transaction = session.beginTransaction();
session.delete(object);
transaction.commit();
}
// 析构函数,中断Session,相当于中断数据库的连接
protected void finalize() throws Exception {
if (session.isConnected() || session != null) {
session.close();
}
}
}
@SuppressWarnings("unchecked")
public class HibernateMultiTableTest {
public static void main(String args[]) {
dbDAO db = new dbDAO();
List<Object> resultList = db
.query("select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'")
.list();//HQL的多表查询
System.out.println("usertable中username为a的用户,发表的内容如下:");
System.out.println();
for (int i = 0; i < resultList.size(); i++) {
Object[] obj = (Object[]) resultList.get(i);
System.out.println("标题:" + obj[0]);
System.out.println("内容:" + obj[1]);
System.out.println();
}
}
}
其运行结果如下:
转载自:yongh701
相关文章推荐
- hibernate查询出的数据和数据库不一致
- hibernate实现多表查询处理返回多个对象结果
- Hibernate多对多关联映射的HQL中的in条件查询问题
- 关于Hibernate中如果一个实体类是 Set,怎么去查询数据
- Hibernate查询解决方案
- Hibernate原生SQL查询
- Hibernate根据查询内容封装成对象(DTO)
- day34_hibernate二级&查询缓存
- Timestamp(时间戳)计算的小问题,注意将其强制转换为long。Hibernate时间段查询。
- Hibernate结合JPA编写通用泛型多条件查询
- hibernate之查询进行优化
- hibernate3.0发现在海量数据表中查询很慢 ,不在于问题,在于解决问题的思路啊,学习了
- hibernate查询
- Hibernate HQL插入、查询、删除操作
- Hibernate Hql 做查询和hibernateArgs 说明
- Hibernate里面如何用Criteria 查询记录数
- hibernate在命名查询named queries中使用native sql
- Hibernate实现模糊查询的方法
- Hibernate中的数据查询(二)
- Hibernate查询语言:HQL