Hibernate绑定到Weblogic的JNDI上的问题(尤其请robbin指教)

1、首先在Weblogic上配置一个连接池quickstart。JNDI名称也是quickstart。

2、编写一个Weblogic的启动类。该类完全参考Hibernate站点上的例子。http://hibernate.bluemars.net/74.html
3、Hibernate的配置文件定义如下:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">

<hibernate-configuration>

<session-factory>

<property name="connection.datasource">quickstart</property>
<property name="show_sql">false</property>
<property name="use_outer_join">true</property>
<property name="dialect">net.sf.hibernate.dialect.OracleDialect</property>

<!-- Mapping files -->
<mapping resource="OrderBase.hbm.xml"/>

</session-factory>

</hibernate-configuration>

4、将POJO持久类、启动类和映射文件打包到一个文件POJO.jar;同时将Hibernate需要的Jar文件和POJO.jar文件放到Weblogic的启动CLASSPATH上去。

4、启动Weblogic,配置一个启动类。指向我们刚创建的Hibernate启动类;
5、关闭Weblogic,重新启动,结果如下:
开始绑定Hibernate对象.
10:28:18,593 INFO Environment:377 - Hibernate 2.0 beta 5
10:28:18,593 INFO Environment:406 - hibernate.properties not found
10:28:18,593 INFO Environment:426 - using CGLIB reflection optimizer
10:28:18,593 INFO Environment:436 - JVM proxy support: true
10:28:18,609 INFO Configuration:264 - Mapping resource: com/huawei/ibss/po/Orde
rBase.hbm.xml
10:28:18,750 INFO Collection:166 - Mapping class: com.huawei.ibss.po.OrderBase
-> ORDERBASE
10:28:19,125 INFO SessionFactoryImpl:122 - building session factory
10:28:19,140 WARN SessionFactoryImpl:140 - No dialect set - using GenericDialec
t: The dialect was not set. Set the property hibernate.dialect.
10:28:19,140 INFO Dialect:36 - Using dialect: net.sf.hibernate.dialect.GenericD
ialect
10:28:19,156 WARN UserSuppliedConnectionProvider:24 - No connection properties
specified - the user must supply JDBC connections
10:28:19,156 INFO SessionFactoryImpl:155 - Use outer join fetching: false
10:28:19,156 INFO SessionFactoryImpl:178 - Use scrollable result sets: false
10:28:19,531 INFO SessionFactoryObjectFactory:82 - no JDNI name configured
10:28:19,531 INFO SessionFactoryImpl:272 - Query language substitutions: {}
绑定完成!

问题:明明我在Hibernate的配置文件里申明了用的是Oracle的Dialect。但是启动的时候并没有使用Oracle的。这就导致了数据库连接无法找到。连接池的配置没有问题。JNDI也可以看到。测试都可以连接数据库。

请教是什么原因?

步骤三的Hibernate配置文件显示有问题。添加如下:
< ?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">

< hibernate-configuration>

< session-factory>

< property name="connection.datasource">quickstart</property>
< property name="show_sql">false</property>
< property name="use_outer_join">true</property>
< property name="dialect">net.sf.hibernate.dialect.OracleDialect</property>

<!-- Mapping files -->
< mapping resource="OrderBase.hbm.xml"/>

< /session-factory>

< /hibernate-configuration>

查了手册,似乎忘了添加hibernate.properties文件。添加如下:

hibernate.dialect=net.sf.hibernate.dialect.OracleDialect
hibernate.connection.datasource=quickstart
hibernate.connection.pool_size=1
hibernate.statement_cache.size=25
hibernate.connection.provider_class=net.sf.hibernate.connection.DatasourceConnectionProvider

hibernate.jdbc.fetch_size=50
hibernate.jdbc.batch_size=25

并将该文件打包到POJO.jar里的classes目录下(和Hibernate.cfg.xml同一个目录)。重新启动Weblogic提示错误如下:

开始绑定Hibernate对象.
11:14:21,984 INFO Environment:377 - Hibernate 2.0 beta 5
11:14:22,000 INFO Environment:411 - loaded properties from resource hibernate.p
roperties: {hibernate.cglib.use_reflection_optimizer=true, hibernate.dialect=net
.sf.hibernate.dialect.OracleDialect, hibernate.jdbc.batch_size=25, hibernate.jdb
c.fetch_size=50, hibernate.connection.provider_class=net.sf.hibernate.connection
.DatasourceConnectionProvider, hibernate.connection.datasource=quickstart }
11:14:22,000 INFO Environment:426 - using CGLIB reflection optimizer
11:14:22,000 INFO Environment:436 - JVM proxy support: true
11:14:22,000 INFO Configuration:264 - Mapping resource: com/huawei/ibss/po/Orde
rBase.hbm.xml
11:14:22,156 INFO Collection:166 - Mapping class: com.huawei.test.po.OrderBase
-> ORDERBASE
11:14:22,578 INFO SessionFactoryImpl:122 - building session factory
11:14:22,578 INFO Dialect:36 - Using dialect: net.sf.hibernate.dialect.OracleDi
alect
11:14:22,578 INFO ConnectionProviderFactory:52 - Initializing connection provid
er: net.sf.hibernate.connection.DatasourceConnectionProvider
11:14:22,593 INFO NamingHelper:26 - JNDI InitialContext properties:{}
11:14:22,593 FATAL DatasourceConnectionProvider:47 - Could not find datasource:
quickstart
javax.naming.NameNotFoundException: Unable to resolve 'quickstart ' Resolved ; r
emaining name 'quickstart '

11:14:22,593 FATAL DatasourceConnectionProvider:47 - Could not find datasource:
quickstart
javax.naming.NameNotFoundException: Unable to resolve 'quickstart ' Resolved ; r
emaining name 'quickstart '

Hibernate找不到你的数据库连接池。

但是我在Weblogic的启动类的startup方法里编写了一段测试代码:

// try
// {
// if(context.lookup("quickstart") != null )
// System.out.println("可以获取JNDI--quickstart");
// else
// System.out.println("无法获取JNDI--quickstart");
// }
// catch(Exception e)
// {
// System.out.println("获取JNDI--quickstart出错!");
// }
打印的结果是contex可以lookup到该数据源的JNDI名称的。这句提示:
11:34:25,015 INFO NamingHelper:26 - JNDI InitialContext properties:{}

跟踪到Hibernate的源代码里看,似乎它返回的Context是一个new的新的:
new InitialContext();

不知何解?

你看看我那个在Weblogic上配置Hibernate帖子最下面的分析好吧。

感谢robbin详尽的分析。
我参考Weblogic下的代码:
private static void doBind( ) throws Exception
{
Properties environment = null;
InitialContext context = null;

try
{
//Properties for storing JNDI configuration information
environment = new Properties( );

//Add initial context factory
environment.put( Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
environment.put( Context.PROVIDER_URL, URL );
log( "Constructing an Initial Directory Context object" );
context = new InitialContext( environment );

Configuration conf = new Configuration().addClass(Cat.class);
SessionFactory factory = conf.buildSessionFactory();

if (factory == null)
throw new Exception("SessionFactory cannot be built?!");

try
{
if( context.lookup(SESSION_FACTORY_JNDI ) != null )
context.rebind(SESSION_FACTORY_JNDI, factory );
else
context.bind(SESSION_FACTORY_JNDI, factory );
}
catch ( NamingException nameEx )
{
context.bind(SESSION_FACTORY_JNDI, factory );
}

}

可是我跟踪发现,程序执行到SessionFactory factory = ds.buildSessionFactory(); 就已经抛出上述的异常。即找不到数据源quickstart。在Hibernate的站点上Govin提供的例子里
Datastore ds = Hibernate.createDatastore();

的Datastore是否是老版本的实现?2.01版本里没有该类。

这个问题比较土。我自己搞定吧。
robbin是正确的,找不到datasource是因为我在配置文件里的datasource的JNDI后面搞了一个空格!!

其实这个问题也不能算土,因为我也碰到过,因为配置文件后面的空格导致找不到错误原因。这算是一个很好的troubleshooting的例子。

不过我在UltraEdit的时候就可以避免该问题的发生,因为UltraEdit有一项功能会在你保存文件的时候自动截掉行尾的空格。