Hibernate级联查询应用的困惑。
比如举个简单的例子:制作一个博客系统,其中有会员,文章分类,对应具体类别的文章。
很明显会员与文章类别之间的映射关系是一对多,文章类别与文章之间的映射关系是一对多。
为了实现他们的查询我可以采用好几种方法:
1:我将他们之间都设置为一对多单向映射而且是立即加载。
在会员登陆的同时我就加载所有的级联对象。这是个Action方法,里面返回一个Map类型数据,而在Map里包含了会员,文章分类以及文章的集合类型List,同时把他们
都至于Sessions中,或者Request中。
然后这个Action返回该用户的博客界面,里面我用<logic:present name="result"><logic:iterate id="order" name="result" type="com.ORM.Orders">这种Structs标签把他们的值取出并展示在界面上。同时由于全部博客信息都已经加载,那样的话我可以只用一个界面就可以满足用户对博客信息的各种查询,意思就是说我会利用JavaScript动态现实用户查询信息需要的DIV片段。那样的话代码变得很简单,而且用户体验会很不错,基本上和AJAX的效果差不多,因为所有信息随着用户第一次打开博客界面,都已经生成各个对应的Div片段啊只不过我把它们利用JavaScript和CSS技术都隐藏啦。然后更具用户的各种需求在把包含用户信息的Div片段显示出来!
当然这种情况很容易实现。但是Hibernate查询效率问题需要思考。
2:我只是将会员与文章类别级联,然后在博客主界面先显示文章类别,至于具体文章的加载则是有用户自己决定,这样的话我就必须额外的Action类或者是其他Action类中增加对应的更具条件加载对应文章的方法。那样的话我只能在另一个页面生成用户所要的结果(文章的具体信息),因为Action类可定会生成一个返回界面的
ActionForward对象。那样的话无疑增加了复杂度。但是与前面的方法比较查询效率可定要好一些,但是需要额外增加很多JSP展示界面,代码变得更加复杂。
3:直接利用连接池+SQL语句直接查询,这样的话查询效率更高,因为它避开了Hibernate对SQL的一些封装而且显得更加灵活,但是那些SQL语句有太麻烦,又由于本人很喜欢Hibernate所以还是觉得不舒服。
现在真的很困惑,方法多很好,但方法的选择却很痛苦!
关于第二种方法我想更加仔细的说一下。
按照前面的思路,用户登陆后就打开了博客主界面,上面显示了该博客里的文章分类。然后主动权就交给用户啦。他点击一个分类然后就会对应一个Action方法
,Action方法里会调用相关Service类(利用Hibernate技术与数据库打交道)假设传递的参数是类别的ID,那么在Service类里我们怎么检索对应文章
信息呢?我们可以用HQL语句查询,不过这时候就没有必要对类别与文章做一对多映射啦(采用延迟加载)。但我想充分利用Hibernate提供的集合对象的映射。那样的话我提前就为它们做了一对多的映射。我可以考虑利用具体的类别对象直接调用getTopics()返回Set然后再装换成List对象给视图。但这里就出现了一个不舒服的地方就是前面我已经加载了所有的类别对象,当然这是所有的类别对象已经处于托管状态啦!这是我还要重新加载对应ID的持久化对象但好像会出错,因为前面你已经加载过啦啊。如果我重新关联该ID对应的持久化对象似乎又不行,好像托管对象的引用并不能在这个方法中被识别。如果持久化对象是全局声明的话该多好啊,那样的话我只需要在这个Sessions中重新关联该对象,然后执行级联操作(CLASS.getTopics()),不知道这种问题怎么解决?还有持久化对象应该可以声明成全局对象吧?那样的话会不会更好?
最近看了关于对象序列化,对象反射机制以及进程池和数据库连接池的问题,但还不是特别清楚。这里想试着用那些东西分析一下Hibbernate的大致工作机制,大家多多补充,那样的话我会受益匪浅的!
Hibernate里面有个SessionFactory类,这个类里面包含了一些静态方法以及静态类,我们可以调用这个静态工厂获得与数据库交流的类Sessions:
public static Session currentSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null) {
if (sessionFactory == null) {
try {
cfg.configure(CONFIG_FILE_LOCATION);
sessionFactory = cfg.buildSessionFactory();
}
catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
session = sessionFactory.openSession();
threadLocal.set(session);
}
return session;
}
这个Session应该只有一个实例吧,其他的每个线程使用它的时候都会利用ThreadLocal来生成与本线程对应的Session对象的副本。
下面是一个自己简单实现的数据库连接池程序:
package Service;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.sql.*;
import java.util.*;
public class ConnPool {
static boolean IsInit=false;
static private int ConnNow=0;
static private List<Connection> connections = new ArrayList();
static private String PoolName;
static private String DriverName;
static private String DbId;
static private String UserName;
static private String Password;
static private int MaxConn;
/*public ConnPool(String PoolName, String DriverName, String DbId, String UserName, String Password, int MaxConn) {
this. PoolName = PoolName;
this. DriverName = DriverName;
this. DbId = DbId;
this. UserName = UserName;
this. Password = Password;
this. MaxConn = MaxConn;
initPool();
}*/
public static synchronized void releaseConnection(Connection conn) {
connections.add(conn);
ConnNow--;
}
public static synchronized Connection getConnection() {//获取Connection对象
Connection conn = null;
if (connections.size() > 0) {
conn = (Connection) connections.get(0);
connections.remove(0);
ConnNow++;
}
if(ConnNow==0&&connections.size()==0){
connections=initPool();
conn=getConnection();
}
/* try {
//if (conn.isClosed())
// conn = getConnection();
}
catch (Exception ex) {
ex.printStackTrace();
}
}*/
if(ConnNow==MaxConn){
System.out.print("数据库繁忙!请稍后再试!");
}
return conn;
}
private static List initPool() {
MaxConn=7;
//Class.forName("com.mysql.jdbc.Driver");//Class.forName(DriverName);
if(IsInit==true) {return connections;}
else {
for(int i=0;i<MaxConn;i++){
try {
//conns.add (DriverManager.getConnection(DbId,UserName, Password));
Connection co=DriverManager.getConnection("jdbc:mysql://localhost:3306/chat?useUnicode=true&characterEncoding=gb2312","root","5769358");
connections.add(co);
}
catch(SQLException ex)
{
System.out.print("数据库初始化失败!");
return null;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
IsInit=true;
return connections;
}
}
public static synchronized void closeConn() {
Iterator allConnections= connections.iterator();
while (allConnections.hasNext()) {
Connection conn = (Connection) allConnections.next();
try {
conn.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
connections.clear();
}
public static void main(String args[]) {
Connection conn=ConnPool.getConnection();
try{//Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/chat?useUnicode=true&characterEncoding=gb2312","root","5769358");
Statement stat=conn.createStatement();
stat.execute("insert into user_info (UserName,Password) values('afei','5769358')");
System.out.print(ConnPool.connections.size());
}
catch(SQLException ex)
{
System.err.println(ex.getMessage());
}
finally{
ConnPool.releaseConnection(conn);
ConnPool.closeConn();
}
}
}
可不可以这样理解:Hibernate里的Session类其实就相当于上面程序的Connection类,只不过它对Connection做了封装,可以还封装了其他的一些功能比如事务处理等。
还有一点不同的是Hibernate是利用ThreadLocal机制实现多个线程并发访问同一个Session对象,而上面的是利用synchronized 机制来实现相同的功能。
SessionFactory里还有一个变量: private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";里面包含了所要连接的数据库信息以及其他的一些映射配置(暂且不讨论),然后Hinernate在初始化的时候会利用相关类比如DOM4J解析它,获得相应的数据库理解信息(所要连接的数据库名称,用户密码,用户姓名),再把他们赋值给Session里面的相关变量。然后Session类就会成功的建立。数据库的连接,你就可以利用他的其他封装的功能进行与数据库有关的操作。
分享到:
相关推荐
Hibernate是一个开源的Java框架,主要用于简化企业级应用中的对象关系映射(ORM)处理。它允许开发者使用面向对象的编程模型来操作关系数据库,而无需直接编写SQL语句。源码分析是理解其工作原理、学习设计模式以及...
7. **性能优化**:包括批处理、延迟加载、缓存利用等策略,可以帮助提升Hibernate应用的性能。 如果在实际的PPT中遇到了特定问题,建议首先检查上述常见问题,然后根据具体错误消息进行调试。如果www.willvc.com.cn...
然而,初次接触Hibernate时,由于其丰富的配置选项和复杂的使用方式,不少开发者可能会感到困惑。本文将通过一个六个准备、七个步骤的教程,帮助你全面了解并掌握Hibernate的基础配置与使用。 ### 一、Hibernate...
10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的应对 10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 ...
10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的应对 10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 ...
1. **Spring**:这是一个开源的应用框架,广泛用于构建Java应用,特别是Web应用。Spring提供了依赖注入(DI)和面向切面编程(AOP),简化了开发并支持多种数据库访问。 2. **Hibernate**:是一个对象关系映射(ORM...
总的来说,"jee学生反馈信息小系统"是一个理想的入门项目,它涵盖了JEE开发的核心组件,如Struts和Hibernate,并且它的简洁性使得学习者可以轻松地跟随代码理解JEE应用的工作原理。通过研究这个系统,初学者能够深化...
文档分为两部分,第一部分主要介绍了Struts、Spring和Hibernate三个框架在Java Web开发中的应用和特点,第二部分则是实习生的个人经历和感悟。 第一部分中,我们可以看到,Struts、Spring和Hibernate三个框架在Java...
1. **Java EE框架**:JBoss是Java EE标准的实现者,支持EJB(Enterprise JavaBeans)、JMS(Java Message Service)、JPA(Java Persistence API)、JSF(JavaServer Faces)、JAX-RS(Java API for RESTful Web ...
1. **服务器配置**:在"Install工具地址.txt"文件中,可能包含了如何下载和安装常用的Java Web服务器,如Apache Tomcat(Catalina),这是运行Java Web应用程序的基础。Tomcat是开源的Servlet容器,支持JSP和Servlet...
最后,Java技术的发展是持续的,从JDK的演变到开源项目如Tomcat、Struts和Hibernate的广泛应用,这些工具和框架都在不断地推动着Java技术的进步。因此,保持对新技术的关注和学习,是每个Java开发者成长的关键。 ...
1. 对 OOP、IOC、AOP 的设计理念的理解 OOP(Object-Oriented Programming,面向对象编程)是一种编程范式,它强调对象之间的交互和协作。IOC(Inversion of Control,控制反转)是一种设计模式,它将对象之间的...
### 第07章:应用第三方ORM:Hibernate实现登录用例持久层 ORM(Object-Relational Mapping)框架如Hibernate简化了Java对象与数据库之间的交互。在这里,你将学习如何使用Hibernate作为ORM工具来处理登录用例的...
- **性能调优**:介绍如何通过合理配置提高Hibernate的应用性能。 #### 三、前端与后端协作 - **前后端分离模式**:探讨前后端分离的设计理念及其优势,包括数据交换格式(JSON/XML)、API接口设计规范等内容。 - *...
"Java解惑.pdf"可能是一份专门解答Java开发中常见问题和困惑的文档。开发者在实际工作中可能会遇到各种难题,这份文档可能会提供清晰的解释和解决方案,帮助他们解决实际问题,提高开发效率。 总的来说,《Java葵花...
1. **配置繁琐**:早期版本的Spring配置文件相对复杂,可能会导致初学者感到困惑。 2. **学习曲线**:虽然Spring提供了丰富的功能,但对于新手来说,全面掌握Spring需要一定的时间和努力。 3. **性能问题**:虽然...
Struts 1.3 是一个基于MVC(Model-View-...在实践中,还需要关注性能优化、安全性和与其他技术(如Hibernate、Spring等)的集成。如果你对某个部分感到困惑,可以参考提供的博客链接或其他在线资源进行深入学习。
下面将详细介绍这些工具函数的功能及其应用场景。 ### 自定义EasyUI的加载和解析过程 #### 关键代码段 ```javascript $.parser.auto = false; $(function() { $.messager.progress({ text: '页面加载中...', ...
3. **框架篇**:介绍流行的Java Web框架,如Spring MVC、Struts2或Hibernate,这些框架可以提高开发效率,提供更好的结构和管理机制。 4. **实战篇**:通过实际项目案例,展示如何使用所学知识进行完整的Java Web...