`

Hibernate应用的困惑(1)

阅读更多
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类就会成功的建立。数据库的连接,你就可以利用他的其他封装的功能进行与数据库有关的操作。
                   
分享到:
评论
48 楼 icewubin 2009-06-09  
swit1983 写道
有多少公司用自己的框架啊,还是开源的用的多。

开源的也是要决策和整合的。
47 楼 swit1983 2009-06-09  
有多少公司用自己的框架啊,还是开源的用的多。
46 楼 mhx 2009-06-05  
我们公司的测试很不规范,基本就是人来点点,呵呵。
就我个人,作为一个开发人员我的代码都会有unittest的。
45 楼 jasstion 2009-05-30  
mhx 写道

&nbsp;&nbsp;&nbsp; 楼主,实际动手做做,不要把问题想的那么复杂。什么设计模式、UML都是根据需要来采用的,如果你仅仅写一个批处理根本不需要UML和设计模式之类的东西。 &nbsp;&nbsp;&nbsp; 我建议你先按照自己的思路写出一个可运行的模块。然后再增加新的功能,在这个过程中你就会慢慢发现设计模式和UML之类的东西要用在什么地方了,不要一开始就去研究这些问题。不过,之后还是要好好的读一些相关的书籍,毕竟理论领导实际,但是理论来自实际。

好的,谢谢啊!我现在也是感觉初学者没有必要考虑那些问题,希望暑假能够把个中不同思路都实现一下,然后尽量用有关相关测试软件测试一下查询效率,你们公司一般都是用得什么测试软件?自己回来试着熟悉一下
44 楼 mhx 2009-05-30  
    楼主,实际动手做做,不要把问题想的那么复杂。什么设计模式、UML都是根据需要来采用的,如果你仅仅写一个批处理根本不需要UML和设计模式之类的东西。
    我建议你先按照自己的思路写出一个可运行的模块。然后再增加新的功能,在这个过程中你就会慢慢发现设计模式和UML之类的东西要用在什么地方了,不要一开始就去研究这些问题。不过,之后还是要好好的读一些相关的书籍,毕竟理论领导实际,但是理论来自实际。
43 楼 treblesoftware 2009-05-30  
自己动手试试。软件的复杂度不是你可以预知的。
42 楼 icewubin 2009-05-29  
jasstion 写道
大家是不是误解我的意图啊?我是觉的应用Hibernate解决某个问题会有几种不同的方法,比如上面我举出的例子,但是考虑到代码与效率之间,怎么作出选择?主要是讨论一下Hibenate查询技术的运用,如何做到代码既简单同时效率有比较高。

提醒楼主一下,如果封装得好的话,手工写一个查询一对多关系的方法超级简单,为何一定要想方设法的利用映射配置呢?映射配置是死的,而且不好维护,配置修改的风险太大了,一个POJO是会被很多其他类共享使用的。

映射配置本来就是为了简化查询,但是如果查询本身已经能够做到很简单,为何还要依赖一对多的配置(尤其是在你没有很好掌握一对多配置的情况下)。不过这好像引出另外一个问题了,需要掌握高效、简洁的hql的写法。
41 楼 yuanke52014 2009-05-29  
别来问了,自己练习吧
40 楼 lw223 2009-05-26  
实际做一做就知道怎样了
39 楼 xujunJ2EE 2009-05-26  
hibernate3中获得session可以使用sessionFactory.getCurrentSession(),
并且在commit()之后,session就自动colse了
现在的问题是:我在DAO层定义一个load的方式获得对象,默认是lazy ture的,那么hibernate返回给我的是一个代理对象,并不是持久化对象,这样在service层调用该方法的时候,会出现异常。当然,你可以说用get()不就OK拉,但是如果是对象many-to-one关联呢,还是会有问题的
如果是web项目,并且结合了spring,那么可以使用openSessionViewFilter的方式,但是如果我现在
开发的是C/S项目呢,是不是只能lazy false或者是hibernate.initialize()方式,但这样我就没有方法获得lazy true的优势了。
各位你们怎么处理非web spring项目中的lazy问题
38 楼 Durian 2009-05-26  
1.to download and look over a copy of servlet2.3 reference, that is so called fundation.
37 楼 activemq 2009-05-26  
现在学习 ,电脑的人,学习 java技术的人,真多~~!
36 楼 jasstion 2009-05-25  
giginet 写道

学习框架没什么用,只是代码工人而已,真的。可能我说的有些直白,但事实如此。学框架就是要学它是怎么实现的,明白它的精华。这个道理大家都明白,我就不废话了。 我也面过很多人,都是生套框架,有什么直接丢进框架里,一问为什么,根本不知道。很多都将基础的丢掉了,譬如,很多人用SSH,却还不知道如何写servlet,不懂tomcat,不懂数据库。。。。用了structs,却不知道为什么要这么用,只是搭好了一个模板,往里面添代码,这不是代码工人是什么? lz能提出这个问题说明还不错,至少还从性能等方面去思考了下这个问题。hibernate我也不是很熟,以前刚毕业的时候搞过一段时间,现在发现,还是回到了sql的老路上来了。性能这个东西,放到生产环境中来接受考验,用自己真实测出的数据来说话,才是最真实的,否则别人云如何可以提高效率,自己那么做了,可是为什么,依然不懂。水平也依旧得不到提高。性能这个东西其实很复杂的,很多时候并不仅仅是从代码上考虑的,架构才是最重要的,有的时候也要经过很多试验才能说清楚。 另外,不要因hibernate而hibernate,每个框架都有其优秀之处,但譬如一对多,多对一这种,能不用的时候,就不要用。练手的时候是一个技术,但放到实际应用中,在有些情况下还是不适用的。这个时候就要果断放弃,而不是所有技术的堆积,那样,只会产生反效果。 很多新手刚开始学习的时候都恨不得把所有技术全都放到自己的作品中,我以前也是这样。但随着时间的推移,慢慢你会发现,有的时候简单才是美。现实要的并不是技术,而是好用的产品,仅此而已。

说得很好!的确那些框架技术感觉很美!自己终是想把那些技术全部利用上,但是发现却很难!您说得关于代码工人,的确,框架再好还是别人的东西,别人的思想,如果能够深刻领悟到别人的思想,在加上自己的创新我感觉那是很高境界啊!我还是差的很远,所以一直在努力!希望能够领悟到JAVA WEB编程的思想,那样的话就会以不变应万变啦吧!
35 楼 giginet 2009-05-25  
学习框架没什么用,只是代码工人而已,真的。可能我说的有些直白,但事实如此。学框架就是要学它是怎么实现的,明白它的精华。这个道理大家都明白,我就不废话了。

我也面过很多人,都是生套框架,有什么直接丢进框架里,一问为什么,根本不知道。很多都将基础的丢掉了,譬如,很多人用SSH,却还不知道如何写servlet,不懂tomcat,不懂数据库。。。。用了structs,却不知道为什么要这么用,只是搭好了一个模板,往里面添代码,这不是代码工人是什么?

lz能提出这个问题说明还不错,至少还从性能等方面去思考了下这个问题。hibernate我也不是很熟,以前刚毕业的时候搞过一段时间,现在发现,还是回到了sql的老路上来了。性能这个东西,放到生产环境中来接受考验,用自己真实测出的数据来说话,才是最真实的,否则别人云如何可以提高效率,自己那么做了,可是为什么,依然不懂。水平也依旧得不到提高。性能这个东西其实很复杂的,很多时候并不仅仅是从代码上考虑的,架构才是最重要的,有的时候也要经过很多试验才能说清楚。

另外,不要因hibernate而hibernate,每个框架都有其优秀之处,但譬如一对多,多对一这种,能不用的时候,就不要用。练手的时候是一个技术,但放到实际应用中,在有些情况下还是不适用的。这个时候就要果断放弃,而不是所有技术的堆积,那样,只会产生反效果。

很多新手刚开始学习的时候都恨不得把所有技术全都放到自己的作品中,我以前也是这样。但随着时间的推移,慢慢你会发现,有的时候简单才是美。现实要的并不是技术,而是好用的产品,仅此而已。
34 楼 czwlucky 2009-05-25  
ningzai 写道
我也刚刚学完ssh ,不过我已经工作的朋友说现在没有必要学什么框架了,公司自己有自己的框架,我也不太了解,我现在也和lz一样也还没毕业呢!不过我认为ssh是最基础的东西,不会的话就说不过去了。以后有机会再学其他的。

没有什么东西是不是应该学的,只要你喜欢学就可以。可能工作中你需要SSH,甚至是其他的框架,公司不会等你学会了才开始干的,所以不能说什么框架学会了就如何如何。基础打好了,什么样的框架学起来都不是问题了。 心中有兴趣,学什么都有用的。
33 楼 rrsy23 2009-05-25  
需求决定 采用什么技术,什么就是的什么方式;
如果数据量很少,hibernate lazy=false没有问题

数据量大了 你直接load肯定问题;

所以,那个都可以,看你到底考虑代码简单 还是效率优先,还是折中;
32 楼 ningzai 2009-05-25  
我也刚刚学完ssh ,不过我已经工作的朋友说现在没有必要学什么框架了,公司自己有自己的框架,我也不太了解,我现在也和lz一样也还没毕业呢!不过我认为ssh是最基础的东西,不会的话就说不过去了。以后有机会再学其他的。
31 楼 vlinux 2009-05-24  
别在忽悠楼主,在我们公司,项目经理、业务经理都是有很强的技术背景的。特别是搞计算机这帮酸腐的文人,经常文人相轻,想要部下服你,不是看谁职位高的
30 楼 kjj 2009-05-24  
别学java啦,趁还没定形学点软件工程管理,跑跑业务,比啥都强!!!!
29 楼 jasstion 2009-05-24  
jasstion 写道

whaosoft 写道
我不鄙视你&amp;nbsp; 但是你水平很初级 先弄点基础的 一上来就像上面说的 什么画uml 没用~&amp;nbsp;


呵呵!谢谢你手下留情!不过最重要的是给我些建议啊,写出文章就是为了让高人批的,只有这样才有收获啊,我也就是自学Struts1.x+Hibernate不到半年时间,都是业余时间看的,请教一下高手:什么东西算是基础的啊???

相关推荐

    hibernate_3.1源码

    Hibernate是一个开源的Java框架,主要用于简化企业级应用中的对象关系映射(ORM)处理。它允许开发者使用面向对象的编程模型来操作关系数据库,而无需直接编写SQL语句。源码分析是理解其工作原理、学习设计模式以及...

    hibernate ppt 有问题 www.willvc.com.cn 能联系到我

    7. **性能优化**:包括批处理、延迟加载、缓存利用等策略,可以帮助提升Hibernate应用的性能。 如果在实际的PPT中遇到了特定问题,建议首先检查上述常见问题,然后根据具体错误消息进行调试。如果www.willvc.com.cn...

    hIbernate扫盲篇

    然而,初次接触Hibernate时,由于其丰富的配置选项和复杂的使用方式,不少开发者可能会感到困惑。本文将通过一个六个准备、七个步骤的教程,帮助你全面了解并掌握Hibernate的基础配置与使用。 ### 一、Hibernate...

    Spring3.x企业应用开发实战(完整版) part1

    10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的应对 10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 ...

    Spring.3.x企业应用开发实战(完整版).part2

    10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的应对 10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 ...

    spring-hibernate-jackson-error

    1. **Spring**:这是一个开源的应用框架,广泛用于构建Java应用,特别是Web应用。Spring提供了依赖注入(DI)和面向切面编程(AOP),简化了开发并支持多种数据库访问。 2. **Hibernate**:是一个对象关系映射(ORM...

    jee学生反馈信息小系统

    总的来说,"jee学生反馈信息小系统"是一个理想的入门项目,它涵盖了JEE开发的核心组件,如Struts和Hibernate,并且它的简洁性使得学习者可以轻松地跟随代码理解JEE应用的工作原理。通过研究这个系统,初学者能够深化...

    2020前端开发实习总结范文.doc

    文档分为两部分,第一部分主要介绍了Struts、Spring和Hibernate三个框架在Java Web开发中的应用和特点,第二部分则是实习生的个人经历和感悟。 第一部分中,我们可以看到,Struts、Spring和Hibernate三个框架在Java...

    jboos_document

    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 ...

    Java Web编程宝典源码

    1. **服务器配置**:在"Install工具地址.txt"文件中,可能包含了如何下载和安装常用的Java Web服务器,如Apache Tomcat(Catalina),这是运行Java Web应用程序的基础。Tomcat是开源的Servlet容器,支持JSP和Servlet...

    孙卫琴对大家java学习的一点建议

    最后,Java技术的发展是持续的,从JDK的演变到开源项目如Tomcat、Struts和Hibernate的广泛应用,这些工具和框架都在不断地推动着Java技术的进步。因此,保持对新技术的关注和学习,是每个Java开发者成长的关键。 ...

    (完整版)Java系统架构师面试题.docx

    1. 对 OOP、IOC、AOP 的设计理念的理解 OOP(Object-Oriented Programming,面向对象编程)是一种编程范式,它强调对象之间的交互和协作。IOC(Inversion of Control,控制反转)是一种设计模式,它将对象之间的...

    JSP教程(从入门到精通)第一部分

    ### 第07章:应用第三方ORM:Hibernate实现登录用例持久层 ORM(Object-Relational Mapping)框架如Hibernate简化了Java对象与数据库之间的交互。在这里,你将学习如何使用Hibernate作为ORM工具来处理登录用例的...

    HM深度技术剖析 JAVA Web全新维度 最新JAVA Web全面开发课程 最新技术与综合实战课程

    - **性能调优**:介绍如何通过合理配置提高Hibernate的应用性能。 #### 三、前端与后端协作 - **前后端分离模式**:探讨前后端分离的设计理念及其优势,包括数据交换格式(JSON/XML)、API接口设计规范等内容。 - *...

    Java葵花宝典

    "Java解惑.pdf"可能是一份专门解答Java开发中常见问题和困惑的文档。开发者在实际工作中可能会遇到各种难题,这份文档可能会提供清晰的解释和解决方案,帮助他们解决实际问题,提高开发效率。 总的来说,《Java葵花...

    Spring Live中文

    1. **配置繁琐**:早期版本的Spring配置文件相对复杂,可能会导致初学者感到困惑。 2. **学习曲线**:虽然Spring提供了丰富的功能,但对于新手来说,全面掌握Spring需要一定的时间和努力。 3. **性能问题**:虽然...

    配置 struts1.3

    Struts 1.3 是一个基于MVC(Model-View-...在实践中,还需要关注性能优化、安全性和与其他技术(如Hibernate、Spring等)的集成。如果你对某个部分感到困惑,可以参考提供的博客链接或其他在线资源进行深入学习。

    孙宇syutils

    下面将详细介绍这些工具函数的功能及其应用场景。 ### 自定义EasyUI的加载和解析过程 #### 关键代码段 ```javascript $.parser.auto = false; $(function() { $.messager.progress({ text: '页面加载中...', ...

    Java Web整合开发王者归来光盘内容和PDF文档

    3. **框架篇**:介绍流行的Java Web框架,如Spring MVC、Struts2或Hibernate,这些框架可以提高开发效率,提供更好的结构和管理机制。 4. **实战篇**:通过实际项目案例,展示如何使用所学知识进行完整的Java Web...

Global site tag (gtag.js) - Google Analytics