6) hibernate.session_factory_name

配置一个JNDI名称,通过Configuration对象创建的SessionFactory会绑定到JNDI下该名称中。一般名字格式为jndi/someName。注意,要使用JNDI,需要在具有JNDI功能的环境之中,比如WEB容器或者EJB容器中。

下面再tomcat中做一个示例,首先在一个标准的WEB项目中添加hibernate的一些基本功能,接着在hibernate.properties文件中添加:


hibernate.session_factory_name jndi/sf


创建一个Filter作为Open Session In View过滤器:

public class OpenSessioninViewFilter implements Filter {
public void destroy() {}
public void doFilter(ServletRequest req, ServletResponse resp,

FilterChain chain) throws IOException, ServletException {
HibernateUtil.getInstance().getCurrentSession();
chain.doFilter(req, resp);
HibernateUtil.getInstance().closeSession();
}

public void init(FilterConfig arg0) throws ServletException {}
}

HibernatUtil类的创建过程中就初始化并创建了一个SessionFactory,那么该SessionFactory就已经绑定在了JNDINamingjndi/sf上:

private HibernateUtil() {
sf = new Configuration().configure().buildSessionFactory(
new ServiceRegistryBuilder().buildServiceRegistry());
}
   接着再创建一个Filter来验证JNDI是否绑定成功:

public class SomeFilter implements Filter {

public void destroy() {}
public void doFilter(ServletRequest req, ServletResponse resp,

FilterChain chain) throws IOException, ServletException {
try {
Context ctx = new InitialContext();
System.out.println(ctx.lookup("jndi/sf"));
} catch (Exception e) {
e.printStackTrace();
}
chain.doFilter(req, resp);
}

public void init(FilterConfig arg0) throws ServletException {}
}
Filter仅仅是很简单的从上下文中找到名字为jndi/sf的资源并打印出来。要能够正常打印,必须要保证open session in view 过滤器在该SomeFilter之前运行(主要的目的是要求在第一次使用JNDI查找SessionFactory资源之前完成SessionFactory的实例化):

<filter>
<filter-name>osiv</filter-name>
<filter-class>util.OpenSessioninViewFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>osiv</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
<filter-name>filter</filter-name>
<filter-class>util.SomeFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
运行应用,随意请求一个地址,后台打印:


org.hibernate.internal.SessionFactoryImpl@6186ee4d


已经工作正常。注意一点的就是,如果只是在JUnit中测试Hibernate,在Hibernate启动过程当中就会看到这样的异常:

WARN: HHH000277: Could not bind factory to JNDI
org.hibernate.service.jndi.JndiException: Error parsing JNDI name [foo]
at org.hibernate.service.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:92)
at org.hibernate.service.jndi.internal.JndiServiceImpl.bind(JndiServiceImpl.java:108)
at org.hibernate.internal.SessionFactoryRegistry.addSessionFactory(SessionFactoryRegistry.java:89)
at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:480)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1750)
at cd.itcast.hibernate.day1.jdbc.HibernateUtil.(HibernateUtil.java:15)
at cd.itcast.hibernate.day1.jdbc.HibernateUtil.(HibernateUtil.java:10)
at cd.itcast.hibernate.day1.jdbc.UserTest.test(UserTest.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.getNameParser(Unknown Source)
at org.hibernate.service.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:86)
... 30 more


该异常并不影响Hibernate的正常使用,其原因是因为在hibernateproject/etc/中的hibernate.cfg.xml文件模板中,sessionFactory配置了name这个属性,这个属性同hibernate.session_factory_name作用相同,也是用于指定JNDI绑定名称,因为在JUNIT环境下没有JNDI功能,所以绑定失败,报错。要去掉这个异常,只需要把SessionFactory元素的name属性删除即可。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐