在《【Hibernate】Hibernate的多表查询》(点击打开链接)一文中,已经介绍过,如果利用HQL语句进行多表查询,摆脱查完一张表又取其中的结果再查另一张表的问题。然而,利用HQL语句查询出来的东西,是一个Object数组,我们要进一步对其处理,将其转化为表的实体的实例。
有如下的一个Java工程如《【Hibernate】Hibernate3.x独立运行时的Failed to load class "org.slf4j.impl.StaticLoggerBinder"错误》(点击打开链接)一样配置Hibernate3.x功能:
在数据库test中,如图,Blog记录了用户发表的博客,usertable记录了用户的基本信息。Blog表中的userid与usertable的主键id形成参照完整性。
这两张表在Hibernate的Java工程种分别对应如下实体:
Blog.java
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
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做如下的配置:
<?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>同时在dbDAO.java中定义一系列的数据库操作方法如下:
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(); } } }
select * from blog as t1 ,usertable as t2 where t1.userid=t2.id
在HibernateMultiTableTest中利用Hibernate查询出来。整个查询结果就是一个名为resultList存放Object数组的List,那么,每一行查询结果将是一个Object数组。
从上图可以看出查询结果由表blog、usertable连接产生,而这个Object数组中,Hibernate定义,第0项就是查询结果中表blog的部分,可以利用Java强制类型将其转换Java中的Blog实体,同理第1项的查询结果就是表usertable的部分,可以利用Java强制类型将其转换Java中的Usertable实体。
得到这两个实体之后,可以如同Hibernate往常一样的NoSQL一样,对这两个实体进行操作。
import java.util.List; public class HibernateMultiTableTest { @SuppressWarnings("unchecked") public static void main(String args[]) { dbDAO db = new dbDAO(); List<Object> resultList = db.query( "from Blog as t0,Usertable as t1 where t0.userId=t1.id").list();// HQL的多表查询 for (int i = 0; i < resultList.size(); i++) { Object[] hql_result_arr = (Object[]) resultList.get(i);//取其中一行的查询结果 //将查询结果分成两半,分别转化为相应的实体 Blog blog = (Blog) hql_result_arr[0]; Usertable usertable = (Usertable) hql_result_arr[1]; //输出 System.out.println(blog.getId() + "," + blog.getTitle() + "," + blog.getContent() + "," + blog.getUserId() + "," + usertable.getId() + "," + usertable.getUsername() + "," + usertable.getPassword()); } } }