Как встроить HSQLDB в файл с помощью Spring в веб-приложение

У меня есть веб-приложение с Spring, и оно работает правильно, когда я использую 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>

Я просто меняю эту строку

   <property name="url" value="jdbc:hsqldb:hsql://localhost/images" />    
   ( -- Server mode)

для этого

     <property name="url" value="jdbc:hsqldb:file:data/images" />      
     (-- In file)

И он просто проходит модульный тест и не работает в веб-приложении.

Я предполагаю, что в файловом режиме, когда я запускаю веб-приложение, HSQLDB не находит файл базы данных.

Я уже пытался положить данные базы данных в корень веб-приложения и внутри веб-инфы, и это не работает.


person Community    schedule 04.09.2009    source источник


Ответы (3)


Хорошо, если вы поместите базу данных в банку следующим образом:

<property name="url" value="jdbc:hsqldb:res:/data/images" />

Вы можете использовать его только для чтения, если вы попытаетесь вставить или изменить базу данных, если это не удастся.

Одним из решений является размещение прослушивателя в файле web.xml, чтобы при запуске приложения оно инициализировалось корневым путем веб-приложения.

<?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();
        }



}

И это конфигурация, которую я использую весной:

    <?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. если кто-то может сделать это простым, пожалуйста, напишите ответ.

person atomsfat    schedule 03.12.2009

Я нашел ответ здесь:

http://coding.derkeiler.com/Archive/Java/comp.lang.java.databases/2003-11/0096.html

Я поместил данные в банку в моем проекте persistenceLayerWithData.jar.

Затем я установил это свойство в источник данных:

<property name="url" value="jdbc:hsqldb:res:/data/images" />

И я добавил банку в web-inf/lib и сделал войну (все это с maven) и развернул в tomcat, и это работает, также я развернул его в веб-сфере 7 и тоже работает.

Но когда я запускаю mvn jetty: run, я не думаю, что при запуске причала с maven он не помещает банку в claspath.

person Community    schedule 04.09.2009
comment
Файл базы данных находится в src/main/resources? Кроме того, вы собираетесь редактировать эту базу данных? - person Binil Thomas; 11.10.2009

Вы должны использовать абсолютный путь к файлу. Когда вы запускаете свое веб-приложение, ваш «текущий» (или «рабочий») каталог, скорее всего, является папкой bin вашего сервера приложений. Поэтому, когда вы указываете относительный путь для URL-адреса HSQLDB, он пытается загрузить этот файл оттуда, а не где-то относительно корня вашего веб-приложения.

person ChssPly76    schedule 04.09.2009