问题描述
我有一个带有Spring的webApp,当我在服务器模式下使用HSQLDB时它可以正常工作,但在文件模式下,它只通过了单元测试。这是我的数据来源:
I have a webApp with Spring and it works correctly when I use HSQLDB in server mode, but in file mode, it only passes the unit test. This is my data source:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:hsql://localhost/images" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
我只需更改此行
<property name="url" value="jdbc:hsqldb:hsql://localhost/images" />
( -- Server mode)
此
<property name="url" value="jdbc:hsqldb:file:data/images" />
(-- In file)
它只是通过了单元测试,并且失败了web appp。
And it just passes the unit test, and fails in the web appp.
我想在文件模式下,当我运行webapp时,HSQLDB找不到数据库的文件。
I suppose that in file mode, when I run the webapp, HSQLDB doesn't find the file of the database.
我已经尝试将数据库的数据放在webapp的根目录和web-inf内部,但它不起作用。
I already tried to put the data of the database in the root of the webapp and inside the web-inf, and it doesn't work.
推荐答案
好吧,如果你把数据库放在这个jar里面:
Well if you put the database inside the jar like this:
<property name="url" value="jdbc:hsqldb:res:/data/images" />
如果您尝试插入或修改数据库,则只能将其用作只读。
You only can use it as read only, if you try to insert or modify the database if will fail.
一种解决方案是将一个监听器放在web.xml中,这样当应用程序启动时,它将使用应用程序Web的根路径进行初始化。
One solution is to put a listener in the web.xml so when the application start it will ce initialize with the root path of the application web.
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>maf</display-name>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!--This is to get root of the aplication-->
<listener>
<listener-class>
org.atoms.HsqlDatabaseListener
</listener-class>
</listener>
<!--Este listener se encarga de inicializar todo el contenedor de Spring y mantener una variable en el
ServletContext que apunta a dicho contenedor -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
听众:
package org.atoms;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
*
* @author atomsfat
*/
public class HsqlDatabaseListener implements ServletContextListener {
private ServletContext context = null;
public void contextInitialized(ServletContextEvent event) {
context = event.getServletContext();
String prefix = event.getServletContext().getRealPath("/");
System.out.println("database root " + prefix);
com.atoms.HsqlDatabasePathResolver.getInstance(prefix);
}
public void contextDestroyed(ServletContextEvent event) {
context = event.getServletContext();
}
另一类:
package com.atoms;
/**
*
* @author atomsfat
*/
public class HsqlDatabasePathResolver {
private static HsqlDatabasePathResolver instance ;
private static String applicationPath = "";
private HsqlDatabasePathResolver() {
}
/** Get Instance.
*/
static public synchronized HsqlDatabasePathResolver getInstance(String applicationPath) {
if (instance == null) {
HsqlDatabasePathResolver.applicationPath =
HsqlDatabasePathResolver.normalizePath(applicationPath);
instance = new HsqlDatabasePathResolver();
System.out.println("Inizalizando path : " + HsqlDatabasePathResolver.applicationPath);
}
return instance;
}
public String getApplicationPath() {
return applicationPath;
}
public String getUrlDatabase(String urlDatabase) {
return HsqlDatabasePathResolver.replaceAll(urlDatabase,"{apppath}", applicationPath);
}
/**
*
* replace the "\" character by "/" and remove relative paths
*
* @param path
* @return
*/
public static String normalizePath(String path) {
if (path == null) {
return null;
}
String normalized = path;
if (normalized.equals("/.")) {
return "/";
}
if (normalized.indexOf('\\') >= 0) {
normalized = normalized.replace('\\', '/');
}
if (!normalized.startsWith("/") && normalized.indexOf(':') < 0) {
normalized = "/" + normalized;
}
do {
int index = normalized.indexOf("//");
if (index < 0) {
break;
}
normalized = normalized.substring(0, index) + normalized.substring(index + 1);
} while (true);
do {
int index = normalized.indexOf("/./");
if (index < 0) {
break;
}
normalized = normalized.substring(0, index) + normalized.substring(index + 2);
} while (true);
do {
int index = normalized.indexOf("/../");
if (index >= 0) {
if (index == 0) {
return null;
}
int index2 = normalized.lastIndexOf('/', index - 1);
normalized = normalized.substring(0, index2) + normalized.substring(index + 3);
} else {
return normalized;
}
} while (true);
}
public static String replaceAll(String str, String match, String replace) {
if (match == null || match.length() == 0) {
return str;
}
if (replace == null) {
replace = "";
}
if(match.equals(replace))return str;
StringBuffer ret=new StringBuffer();
int i = str.indexOf(match);
int y = 0;
while (i >= 0)
{
//System.out.println("i:"+i+" y:"+y);
ret.append(str.substring(y, i));
ret.append(replace);
//str = str.substring(y, i) + replace + str.substring(i + match.length());
y = i + match.length();
i = str.indexOf(match,y);
}
ret.append(str.substring(y));
return ret.toString();
}
}
这是我在春天使用的配置:
And this the configuration that I use in spring:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">
<!-- La definición del Datasource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" lazy-init="true"
destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url">
<ref bean="dataBaseUrl"/>
</property>
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
<!-- La definición del Factory de Session con Anotaciones -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" lazy-init="false">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>Atoms.hbm.xml</value>
</list>
</property>
</bean>
<!--HibernaTemplate-->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!-- Definición de los DAO`s -->
<bean id="ipBlancaDao" class="org.atoms.impl.AtomsDaoHibernateImpl">
<property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>
<!--If your are not running in Web this will initialize with the directory from the process was started note that this classes is a singleton so if you are running in web the listener already have initialize the class with the path of the class-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<bean id="hsqlDatabasePathResolver" class="com.atoms.HsqlDatabasePathResolver" factory-method="getInstance" lazy-init="false">
<constructor-arg>
<value>${user.dir}</value>
</constructor-arg>
</bean>
<!--This bean just replace {apppath} whit the absolute path-->
<bean id="dataBaseUrl" class="java.lang.String" factory-bean="hsqlDatabasePathResolver" lazy-init="false"
factory-method="getUrlDatabase">
<constructor-arg>
<value>jdbc:hsqldb:mem:{apppath}/WEB-INF/data/maf</value>
</constructor-arg>
</bean>
</beans>
是的,这项工作但是很乱,我认为解决方案是听众,有了它你可以获得appWeb的路径。如果有人可以这么简单,请发布答案。
And yes this work but is a mess , I think that the solution is the listener, with it you can get the path of the appWeb. if somebody can make this simple, please post the answer.
这篇关于如何将Spring中的HSQLDB嵌入到WebApp中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!