|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
用java开发web只要两本书:一本是关于java基础的,一本是关于jsp、servlet的就可以了。开发周期长,我就来讲句题外话,现在有很多思想都是通过java来展现。 今朝人们很简单发明Hibernate正敏捷的成为盛行的J2EE的O/R映照工具和数据集成框架(假如不是最盛行的)。Hibernate为企业使用开辟者操纵干系数据库的供应了明晰了然而又壮大的工具。但是假如你必要在内部会见那些包装在J2EEweb使用里的实体,情形又如何呢?你的开辟跟使用自力分隔,却又不异的实体以会见你的数据吗?又大概你得编写附加的web组件来办理对数据的外部会见吗?
在良多情形下,这些成绩城市呈现。我的情形是我的公司必要未来自多个供给商,有着多种文件格局的纪录导进到数据库里。我想起我之前常常利用的办法,那就是编写Shell和SQL教本(乃至是存储历程)来导进数据。可是因为我们的数据模子太甚庞大,我决意在web使用以外尽量的使用现有的实体,SpringDAO和服务而且开辟一个自界说的J2SE命令行数据加载工具。
年夜成绩:你该如何呢?
如今良多Hibernate的文档和典范都是绑定在容器上。不论是web使用仍是外部的年夜型使用,总会利用到容器的。人们有很好的来由往利用它。容器是计划来供应对各类特征的撑持,比方事件处置,线程和平安。当今,这些特征都是开辟中等范围和企业使用所必须的工具。但是当你必要在容器以外会见实体时,你该如何呢?你是利用现有的架构和代码呢,仍是会从一个分歧的角度来办理成绩,好比说完整接纳另外一种开辟言语?固然,我们没有准确谜底。在本文的余下部分,我将申明我的办法:就是在Spring容器以外重用现有的实体/POJO。
后来,剧本言语,比方Perl,Python,Ruby乃至Tcl(是的,我之前也做过这个)看起来有良多上风。它们能省下良多工夫,能够容易失掉初始了局,还能躲避很多Hibernate潜伏的庞大度。人们完整大概只用几行代码就能够毗连数据库,查询了局,已打印输入到终端屏幕大概日记文件。但是,取决于你的数据模子,事变也(老是)会变得相称庞大。比如说你有一个表person,个中有一个外键属于表address。当我们增加数据的时分,表address没有准确的拔出数据,就会招致表person也不克不及拔出了。这是个很典范的事件处置方面的成绩。大概有人会说在剧本言语中这个成绩不难明决,就像在你的主程序里一样。但是成绩仍旧存在,为何要如许做呢?营业逻辑不是已在你的使用内里了吗?为何要在写一遍代码呢?并且这并非独一的情形,你必需反复你的事情和营业逻辑,如许就会带来堕落的大概。
但是,有些人会以为如许也行,他们利用本人以为最合适的工具。大概你已由于程序以外的缘故原由而有了某种自力的架构;大概你会在自力的数据库里加载和测试数据,然后在经由过程各类测试后再迁徙到产物的数据库里;又大概你把数据库保护外包进来,你只必要把相干文件发给互助同伴让他们去向理那些成绩。总之,总会有良多来由不利用现有的Hibernate数据层。没有谁对谁错,只是假如你能够也乐意在你的使用以外利用现有的代码,请往下看。我会告知你一些办法,这能办理你很多的懊恼噢。
设置
假如你以为能够在容器以外利用现有的Hibernate对象的话,那你起首要做的事就是得本人手工办理一切的设置项,在本文余下部分我所接纳的办法是利用一个基于命令行的JAVA程序。既然你已设置了HibernateXML设置文件,你应当晓得必要供应的参数,比方JNDIDataSource名,实体映照文件,另有其他一些处置SQL日记的属性。假如你想利用命令路程序的话,你就得办理怎样剖析XML文件和把它增加到设置项中的这些成绩。固然剖析XML文件也不难,但这自己并非我们的重点。因而,我倡议利用propetries文件,properties文件对照直不雅并且简单加载并从中读取数据。上面是设置Hibernate所必要的最小属性集(不包含任何实体映照)。
清单1:
hibernate.dialect=net.sf.hibernate.dialect.PostgreSQLDialect
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.connection.url=jdbc:postgresql://devserver/devdb
hibernate.connection.username=dbuserhibernate.connection.password=dbpassword
hibernate.query.substitutionsyesY
正如你所看到的,下面的属性值指定了数据库方言,JDBC驱动,数据库url,用户名,用户暗码,和是不是利用查找交换。只需界说以上几项数值并保留在文件hibernate.properties里(要安排在你的类路径内里哦),就可以很轻松的加载,添补到HibernateConfiguation类内里。
清单2:
Propertiesprops=newProperties();
try{
props.load(props.getClass().getResourceAsStream("hibernate.properties"));
}catch(Exceptione){
System.out.println("Errorloadinghibernateproperties.");
e.printStackTrace();
System.exit(0);
}
Stringdriver=props.getProperty("hibernate.connection.driver_class");
StringconnUrl=props.getProperty("hibernate.connection.url");
Stringusername=props.getProperty("hibernate.connection.username");
Stringpassword=props.getProperty("hibernate.connection.password");
//Inmyexamples,IusePostgres,butHibernate
//supportsvirtuallyeverypopulardbmsout
there.Class.forName("org.postgresql.Driver");
Connectionconn=DriverManager.getConnection(connUrl,username,password);
Configurationcfg=newConfiguration();
cfg.setProperties(props);
SessionFactorysessions=cfg.buildSessionFactory();
Sessionsession=sessions.openSession(conn);
如许我们就失掉了HibernateSession类了。但我们也有需要办理怎样使用现有的实体映照这个成绩。在《HibernateinAction》一书中,提到如何从实体映照XML文件中加载,以下所示:
清单3:
Configurationcfg=newConfiguration();
cfg.addResource("hello/Message.hbm.xml");
cfg.setProperties(System.getProperties());
SessionFactorysessions=cfg.buildSessionFactory();
这段代码明晰的申明了从hello包里加载Message实体界说的历程。关于这个例子来讲还好,但对那些有多个实体的使用来讲,就很单一并且简单堕落。不但映照干系是硬编码,还到手工办理每次增加一个新的实体就要更新实体加载的代码。实在有跟复杂的办法往查找和加载映照干系以使其与最新的jar文件坚持分歧。
起首,在你的web服务器大概企业服务器里,映照文件必要安排在类路径里,如许Hibernate才干一般的运转。如许做是很有优点的,由于你所必要做的就是利用一样的jar包和查找响应的映照文件的名字。由于你大概会有多个jar文件在你的类路径里,你必要指定哪一个jar包包括了映照文件。以下就是一种查找映照干系的办法
清单4:
Stringcp=System.getProperty("java.class.path");
StringjarFile=null;
ListhbmList=null;String[]cparr=cp.split(":");
for(intj=0;j<cparr.length;j++){
//Thefollowingassumesourentities
//arewrappedupinajarfile
//calleddbobjs.jar
if(cparr[j].indexOf("dbobjs.jar")!=-1)
jarFile=(cparr[j]);
}
if(jarFile!=null){
JarFilejar=newJarFile(newFile(jarFile));
Enumeratione=jar.entries();
if(e.hasMoreElements())
{
hbmList=newArrayList();
while(e.hasMoreElements()){
//ObjectcomesbackasJarFile$JarFileEntry
JarEntryentry=(JarEntry)e.nextElement();
if(entry.getName().indexOf(".hbm.xml")!=-1)
{
hbmList.add(entry.getName());
}
}
}else{
System.out.println("Error:Theentityjardbobjs.jarwasnotfoundin"+"classpath:"+cp);
}
}
下面的代码次要完成了以下几件事变:猎取Java假造机初始化的classpath体系属性;查找含有实体映照文件的jar包;剖析映照文件的名字,然后增加到一个ArrayList对象中往。当我们的ArrayList对象装满了实体映照的名字后,就能够将其传送到HibernateConfiguration对象,以下所示:
清单5:
Configurationcfg=newConfiguration();
Iteratoriterator=hbmFileNames.iterator();
while(iterator.hasNext()){
cfg.addResource((String)iterator.next());
}
只需我们在HibernateSession对象里设置好准确的映照干系,我们就能够将实体拿来利用了。
<P> 利用Session
关于这一点,你能够参考关于Hibernate和耐久层的文章大概指南,也能够查询各类对象和实例来懂得怎样利用事件,以是我不盘算具体说这些内容。相反,我会更多思索利用实体后我们必要做甚么?这会对HibernateSession对象有如何的影响?是不是可使用现有的营业对象,乃至是数据会见对象?当我创建数据层的时分,我利用了Spring及其供应的一些类来办理数据库毗连,事件和会话。这些对象都在XML设置文件内里界说了,并与良多划定规矩和干系严密集成在Spring里。起首,经由过程Spring的依附打针,DAO对象会被引进到使用服务中(关于依附打针,拜见BruceTate的《FiveThingsILoveAboutSpring》一书)。然后,设置使用服务以捕捉DAO非常(经由过程XML设置文件),让Spring去向理。但是由于我以为把Spring集成到数据加载使用里会带来相称年夜的事情量。我对DAO对象做了稍微的修正,使得能够在web使用以外利用他们。
比方说在PersonDAO类内里有一个保留person对象的办法。假如HibernateSession是由容器创建的,那这个办法就不克不及在容器外利用,由于这必要一个设置好的Session对象。以下是一个典范的PersonDAO,它由Spring容器供应了对Session的撑持。
清单6:
importorg.springframework.orm.hibernate.HibernateTemplate;
importtest.pojos.Person;
publicclassPersonDAOextendsHibernateTemplate
{
publicPersonDAO(){}publicPersonsave(PersonaPerson)
{
if(aPerson!=null)
super.save(person);
returnperson;
}
}
下面的类承继的是SpringHibernateTemplate类,它供应了各类不错的利用Hibernate的基类办法。并且因为HibernateTemplate类保护了年夜多半的罕见操纵,你就只必要专注特定的耐久层需求。固然也应当有响应的非常处置,但在本次典范傍边,只需以上的就够了。
如今,要在容器外加上对Session的撑持,我们只必要做一些小小的修改:
清单7:
importorg.springframework.orm.hibernate.HibernateTemplate;
importnet.sf.hibernate.Session;
importtest.pojos.Person;
publicclassPersonDAOextendsHibernateTemplate
{
publicPersonDAO(){}
publicvoidsetExternalSessionFactory(SessionaSession){
setSessionFactory(session.getSessionFactory());
}
publicPersonsave(PersonaPerson){
if(aPerson!=null)
super.save(person);
returnperson;
}
}
由于HibernateTemplate类承继于HibernateAccessor类,我们就能够从任何Session对象中创建SessionFactory。这是Spring小组的一个高天真性的计划,使得重用现有代码加倍简单。
大概你并没有利用Spring而是接纳完整分歧的办法。假如你不喜好Spring的一来打针,你也能够经由过程JNDI查找Session对象:
清单8:
importnet.sf.hibernate.Session;publicclassPersonDAO{
//ThisexampleassumesthatthereisaHibernate
//SessionobjectatthefollowingJNDIlocation
//onaTomcat5.5server:
//java:/comp/env/obj/hibernateSession
privateSessionsession;
publicPersonDAO(){
try{
ContextinitCtx=newInitialContext();
ContextenvCtx=(Context)initCtx.lookup("java:comp/env");
session=(Session)envCtx.lookup("obj/hibernateSession");
}catch(Exceptione){
e.printStackTrace();
}
}
publicPersonsave(PersonaPerson){
if(aPerson!=null)session.save(person);
returnperson;
}
}
以上的例子依附于使用服务器来使得HibernateSession对象可用。在容器以外利用的最复杂办法就是增加一个带Session参数的机关函数,以下所示:
清单9:
importnet.sf.hibernate.Session;
publicclassPersonDAO
{
//ThisexampleassumesthatthereisaHibernate
//SessionobjectatthefollowingJNDIlocation
//onaTomcat5.5server:
//java:/comp/env/obj/hibernateSession
privateSessionsession;
publicPersonDAO(){
try{
ContextinitCtx=newInitialContext();
ContextenvCtx=(Context)initCtx.lookup("java:comp/env");
session=(Session)envCtx.lookup("obj/hibernateSession");
}catch(Exceptione){
e.printStackTrace();
}
}
publicPersonDAO(SessionaSession){
session=aSession;
}
publicPersonsave(PersonaPerson){
if(aPerson!=null)session.save(person);
returnperson;
}
}
固然我们并没有处置太多的非常,事件成绩。乃至我们在多个办法内共用一个Session对象,这会招致一些并发事件成绩(取决于容器或框架怎样处置对象实例)。不外我想很明显以上的例子演示了怎样重用大批的现无数据层代码。只必要一点点有制造力的设法。要弄分明你是不是想在使用服务器以外利用现有的实体和DAO,接上去就不休实验把。
结论
正如你所见,要在web容器外利用Hibernate实体和DAO是必要技能的,但这一定能做到的。最年夜的坚苦在于怎样查找实体映照干系和怎样重设置(大概说修正)现有的数据会见对象(即DAO)。处置后者时,要当心处置事件成绩,由于没有使用服务能够依附了。不外最初,我们仍是能够会见一切的实体和举行耐久化的对象,如许能省下大批的从头开辟代码的工夫。祝您好运!!
C#是盗用了Java的源代码,仿照开发的,原因是Java是开源的啊,盗了也白盗,还有一点,开发C#语言的团队是就是开发Java语言的团队,是微软重金挖过去的啊 |
|