Java 如何使用 Spring 在文件中嵌入 HSQLDB 到 WebApp
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1380882/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to embed HSQLDB in file with Spring to a WebApp
提问by
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:
我有一个带有 Spring 的 webApp,当我在服务器模式下使用 HSQLDB 时它可以正常工作,但在文件模式下,它只通过了单元测试。这是我的数据源:
<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>
I just change this line
我只是改变这一行
<property name="url" value="jdbc:hsqldb:hsql://localhost/images" />
( -- Server mode)
for this
为了这
<property name="url" value="jdbc:hsqldb:file:data/images" />
(-- In file)
And it just passes the unit test, and fails in the web appp.
它只是通过了单元测试,但在 web appp 中失败了。
I suppose that in file mode, when I run the webapp, HSQLDB doesn't find the file of the database.
我想在文件模式下,当我运行 webapp 时,HSQLDB 找不到数据库的文件。
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.
我已经尝试将数据库的数据放在 webapp 的根目录和 web-inf 内部,但它不起作用。
回答by ChssPly76
You should use an absolute file path. When you run your web application, your "current" (or "working") directory is most likely the bin
folder of your application server. Therefore, when you specify relative path for HSQLDB URL it tries to load this file from there as opposed to somewhere relative to your webapp root.
您应该使用绝对文件路径。当您运行 Web 应用程序时,您的“当前”(或“工作”)目录很可能bin
是您的应用程序服务器的文件夹。因此,当您为 HSQLDB URL 指定相对路径时,它会尝试从那里加载此文件,而不是相对于您的 web 应用程序根目录的某个位置。
回答by ChssPly76
I found the answer here:
我在这里找到了答案:
http://coding.derkeiler.com/Archive/Java/comp.lang.java.databases/2003-11/0096.html
http://coding.derkeiler.com/Archive/Java/comp.lang.java.databases/2003-11/0096.html
I put de data inside in a jar on my project persistenceLayerWithData.jar.
我将数据放在我的项目persistenceLayerWithData.jar 上的一个罐子里。
Then I set this propety to the datasource:
然后我将此属性设置为数据源:
<property name="url" value="jdbc:hsqldb:res:/data/images" />
And I added the jar to the web-inf/lib and make the war (all this with maven) and deploy in tomcat and it works, also I deploy it in websphere 7 and also works.
我将 jar 添加到 web-inf/lib 并进行战争(所有这些都使用 maven)并在 tomcat 中部署并且它可以工作,我也在 websphere 7 中部署它并且也可以工作。
But when I run whit mvn jetty:run it doesn't I suppose that when running jetty whit maven it doesn't put the jar in the claspath.
但是当我运行 whit mvn jetty:run 时,我不认为在运行 jetty whit maven 时它不会将罐子放在 claspath 中。
回答by atomsfat
Well if you put the database inside the jar like this:
好吧,如果你像这样将数据库放在 jar 中:
<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.
您只能将其用作只读,如果您尝试插入或修改数据库将失败。
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.
一种解决方案是在 web.xml 中放置一个侦听器,这样当应用程序启动时,它将使用应用程序 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>
The listener:
听者:
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();
}
The other class:
另一个类:
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:
这是我在 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>
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.
是的,这项工作是一团糟,我认为解决方案是侦听器,有了它,您可以获得 appWeb 的路径。如果有人可以使这个简单,请张贴答案。