扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
因为知道我不需要使用JTA,所以我想知道为什么Hibernate要尝试找到JTA。我打开了Hibernate配置文件(图16),然后寻找Hibernate Synchronizer中的任何可疑之处。无疑有几行是最有嫌疑的:
<property name="hibernate.transaction.factory_class">
net.sf.hibernate.transaction.JTATransactionFactory
</property>
<property name="jta.UserTransaction">
java:comp/UserTransaction
</property>
我试着把上述内容注释掉并再次运行,这第三次运行成功了。运行没有出现错误,我的数据出现在数据库中。哇!运行可以信赖的antdb目标(Developer's Notebook一书的第1章中对此有说明)便可以看到所有数据(确实很简单),如图20所示。如果您要这样做,要确保从一个antschema开始创建数据库模式,或者清空来自前面实验中的任何测试数据。
图20.测试程序所创建的数据
注意,可以在Eclipse中运行Ant目标,具体方法是右击(或控制单击)Package Explorer中的build.xml文件,选择Run An,然后使用Eclipse对话框选择目标。酷吧?
图21.在Eclipse中运行Ant
使用查询取回数据相当简单,尽管这次的代码很接近于常规的使用Hibernate生成的普通数据访问类所使用的代码。即使Hibernate Synchronizer为处理指定查询生成了大量帮助器方法,我还是认为它们中间没有哪一个方法特别有用,因为它们都坚持运行查询后返回结果列表,而不是提供可以直接使用的Query对象。这使您无法使用Query的方便的类型安全的参数设置方法。因为这一点,我决定一定要让RootDAO对象为我提供一个Hibernate Session,以便使用老式的方法。我认为我可以编辑Hibernate Synchronizer使用的任何模板来生成我想要的任何方法,如果我要使用它来开发一个项目,我几乎肯定我会这么做。
实际上,进一步考虑的话,因为当获得一个活动的Session时,您只能处理Query,DAO所提供的方法已经达到了最佳效果。如果您想像我在这个例子中所做的那样处理查询,您必须总是自己进行会话管理。可以把会话管理嵌入到“您自己的”那一半DAO所提供的业务逻辑中,这就可以同时利用两方面的好处了。这正是Hibernate Synchronizer提供的拆分类模型如此有用的另一个原因。我将在下面对此进行深入探讨。
不管怎样,下面是我第一次想出的代码,基本上等同于书中48-49页上给出的代码:
package com.oreilly.hh;
import java.sql.Time;
import java.util.ListIterator;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;
import com.oreilly.hh.dao.TrackDAO;
import com.oreilly.hh.dao._RootDAO;
/**
* Use Hibernate Synchronizer's DAOs to run a query
*/
public class QueryTest3 {
public static void main(String[] args) throws HibernateException {
// Load the configuration file and get a session
_RootDAO.initialize();
Session session = _RootDAO.createSession();
try {
// Print the tracks that will fit in five minutes
Query query = session.getNamedQuery(
TrackDAO.QUERY_COM_OREILLY_HH_TRACKS_NO_LONGER_THAN);
query.setTime("length", Time.valueOf("00:05:00"));
for (ListIterator iter = query.list().listIterator() ;
iter.hasNext() ; ) {
Track aTrack = (Track)iter.next();
System.out.println("Track: \"" + aTrack.getTitle() +
"\", " + aTrack.getPlayTime());
}
} finally {
// No matter what, close the session
session.close();
}
}
}
TrackDAO提供的一个优秀特性是静态常量,通过它,我们可以请求指定查询,消除任何由于字符串输入错误而引起运行时错误的可能性。我喜欢这一点!为这个测试类设置和执行Run配置,将会生成预期的输出,如图22所示。
图22. Eclipse控制台视图中的查询结果
我前面提到过,运行这个类之后,我意识到,借助于Hibernate Synchronizer所提供的模型,可以用一种更好的方法来实现它。因为指定查询是与该数据访问对象相关的映射文件的一项特性,所以如果我们将查询放入TrackDAO对象中(这才是它真正属于的地方),那么这个对象看起来应该是下面这个样子:
package com.oreilly.hh.dao;
import java.sql.Time;
import java.util.List;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Query;
import net.sf.hibernate.Session;
import com.oreilly.hh.base.BaseTrackDAO;
/**
* This class has been automatically generated by Hibernate Synchronizer.
* For more information or documentation, visit The Hibernate Synchronizer page
* at http://www.binamics.com/hibernatesync or contact Joe Hudson at joe@binamics.com.
*
* This is the object class that relates to the TRACK table.
* Any customizations belong here.
*/
public class TrackDAO extends BaseTrackDAO {
// Return the tracks that fit within a particular length of time
public static List getTracksNoLongerThan(Time time)
throws HibernateException
{
Session session = _RootDAO.createSession();
try {
// Print the tracks that will fit in five minutes
Query query = session.getNamedQuery(
QUERY_COM_OREILLY_HH_TRACKS_NO_LONGER_THAN);
query.setTime("length", time);
return query.list();
} finally {
// No matter what, close the session
session.close();
}
}
}
这样做更好更清晰,还进一步简化了QueryTest3中的main()方法:
public static void main(String[] args) throws HibernateException {
// Load the configuration file and get a session
_RootDAO.initialize();
// Print the tracks that fit in five minutes
List tracks = TrackDAO.getTracksNoLongerThan(Time.valueOf("00:05:00"));
for (ListIterator iter = tracks.listIterator() ;
iter.hasNext() ; ) {
Track aTrack = (Track)iter.next();
System.out.println("Track: \"" + aTrack.getTitle() +
"\", " + aTrack.getPlayTime());
}
}
显然,这是一种在使用Hibernate Synchronizer时处理指定查询的方法。做一次快速测试就可以确认它生成同样的输出,而且它的代码也要好很多。
您是否想使用Hibernate Synchronizer来生成它自己的数据访问对象类型暂且放下,我们还有最后一项重要特性要探讨。
编辑映射
Hibernate Synchronizer的一个主要吸引力就在于它为映射文档提供的专业化的编辑器。可以配置这个编辑器,以便只要保存文件就自动重新生成相关数据对象,但是这只是一个锦上添花的功能;即使不打算使用该插件的代码生成器,您也可能希望使用这个编辑器。它为您提供映射文档元素的智能完成功能,以及一个图形化的大纲视图,可以在这个视图中操纵这些元素。
但是,如果从Developer's Notebook一书中的下载源代码开始,就至少得有一项技巧才可以让编辑器工作。在下载的文件中,映射文档的扩展名为“.hbm.xml”,而只有以“.hbm”结尾的文件才能调用编辑器。理论上,可以在Eclipse中配置扩展名映射,以便使具有这两种扩展名的文件都能使用插件的映射文档编辑器,但是我无法使其生效,而且我注意到支持论坛上有人面临着与我相同的问题。所以,至少目前最好的做法就是重命名文件。(如果您坚持使用基于Ant的标准代码生成,请确保更新build.xml中的codegen目标以使用新的扩展名。)
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者