HSQLDB 问题:使用 HSQL 作为使用 JDBC 模板的现有 MVC 应用程序的后端

Posted

技术标签:

【中文标题】HSQLDB 问题:使用 HSQL 作为使用 JDBC 模板的现有 MVC 应用程序的后端【英文标题】:HSQLDB issue: Using HSQL as backend for the existing MVC application using JDBC template 【发布时间】:2012-03-07 08:52:54 【问题描述】:

我使用 spring security 2.0.4 和 spring 2.5 和 HSQLDB 完成了我的 MVC Web 应用程序,在那里我制作了 CRUD 应用程序。对于我已经使用 HSQL 作为数据库的产品。我通过使用在 applicationContext-security.xml 中硬编码的角色来集成安全性,如下所示:

<authentication-provider>
            <user-service id="userDetailsService">
                    <user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />
                    <user name="username" password="password" authorities="ROLE_USER" />
                    <user name="test" password="test" authorities="ROLE_USER" />
            </user-service>
    </authentication-provider>

现在我必须使用我用于角色产品的相同 HSQL 数据库(他们的用户名和密码)。所以我在我的应用程序中做了以下配置:

我的dataAccessContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- business stuff below -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
        <property name="url" value="jdbc:hsqldb:mem:test" />
        <property name="username" value="sa" />
        <property name="password" value="" />
    </bean>

    <bean id="dataSourcePopulator" class="springapp1.service.HsqldbSchemaAndDataPopulator">
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

这是我的 dataSourcePopulator 文件:HsqldbSchemaAndDataPopulator.java

package springapp1.service;

    import javax.sql.DataSource;

    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.util.Assert;

    /**
     * I am responsible for populating the configured datasource
     */
    public class HsqldbSchemaAndDataPopulator implements InitializingBean 

        private JdbcTemplate template;

        /**
         *
         */
        public void afterPropertiesSet() throws Exception 
            Assert.notNull(template, "dataSource required");

            // add tables to represent admin core-domain instances.
            template
                    .execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,"
                            + "PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,"
                            + "ENABLED BOOLEAN NOT NULL);");
            template
                    .execute("CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
            template
                    .execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");

            // add tables to represent bug tracking domain instances.
            // TODO - add project start and end date
            template
                    .execute("CREATE TABLE PROJECTS(ID BIGINT NOT NULL PRIMARY KEY, NAME VARCHAR_IGNORECASE(50) NOT NULL, DESCRIPTION VARCHAR_IGNORECASE(200) NOT NULL);");

            // insert data here
            template
                    .execute("INSERT INTO USERS VALUES('disabled','disabled',FALSE);");
            template.execute("INSERT INTO USERS VALUES('admin','admin',TRUE);");
            template
                    .execute("INSERT INTO USERS VALUES('username','password',TRUE);");
            template.execute("INSERT INTO USERS VALUES('test','test',TRUE);");

            template
                    .execute("INSERT INTO AUTHORITIES VALUES('admin','ROLE_USER');");
            template
                    .execute("INSERT INTO AUTHORITIES VALUES('admin','ROLE_ADMIN');");

            template
                    .execute("INSERT INTO AUTHORITIES VALUES('username','ROLE_USER');");

            template.execute("INSERT INTO AUTHORITIES VALUES('test','ROLE_USER');");

            template
                    .execute("INSERT INTO projects VALUES (1, 'Test Project', 'A description not longer than 200 chars of what project is.');");
            template
                    .execute("INSERT INTO projects VALUES (2, 'Test Project 2', 'Smaller description of project here.');");
        

        public void setDataSource(final DataSource dataSource) 
            this.template = new JdbcTemplate(dataSource);
        
    

我的 web.xml sn-p:

<context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                      /WEB-INF/applicationContext-security.xml
                      /WEB-INF/dataAccessContext.xml
                      /WEB-INF/applicationContext.xml
                </param-value>
 </context-param>

我更新了我的 applicationContext-security.xml 文件

<authentication-provider>
            <jdbc-user-service id="userDetailsService" data-source-ref="dataSource" />
    </authentication-provider>

现在,当我运行应用程序时,它会在 localhost 日志文件中显示以下错误:

Mar 07, 2012 11:32:58 AM org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
Mar 07, 2012 11:33:18 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Mar 07, 2012 11:33:19 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring FrameworkServlet 'springapp1'
Mar 07, 2012 11:33:30 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet springapp1 threw exception
java.sql.SQLException: Table not found in statement [select id, description, price from products]
    at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
    at org.hsqldb.jdbc.jdbcStatement.fetchResult(Unknown Source)
    at org.hsqldb.jdbc.jdbcStatement.executeQuery(Unknown Source)
    at org.apache.commons.dbcp.DelegatingStatement.executeQuery(DelegatingStatement.java:208)
    at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:443)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:396)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:458)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:466)
    at org.springframework.jdbc.core.simple.SimpleJdbcTemplate.query(SimpleJdbcTemplate.java:187)
    at springapp1.repository.JdbcProductDao.getProductList(JdbcProductDao.java:58)
    at springapp1.service.SimpleProductManager.getProducts(SimpleProductManager.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy34.getProducts(Unknown Source)
    at springapp1.web.InventoryController.handleRequest(InventoryController.java:32)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:277)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.concurrent.ConcurrentSessionFilter.doFilterHttp(ConcurrentSessionFilter.java:99)
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
    at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Unknown Source)

而且它在产品列表中查找,而不是在用户信息列表中。

这是我的产品 DAO

 package springapp1.repository;

    import java.util.List;

    import springapp1.domain.Product;

    public interface ProductDao 

        public List<Product> getProductList();

        public void saveProduct(Product prod);

        public void deleteProduct(Product prod);

        public List<Product> retrieveProduct(int id);

        public Product createProduct(Product p);
    

DAO 的实现:

package springapp1.repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;

import springapp1.domain.Product;

public class JdbcProductDao extends SimpleJdbcDaoSupport implements ProductDao 

    public void deleteProduct(Product prod) 
        logger.info("Deleting product with id: " + prod.getId());
        int count = getSimpleJdbcTemplate().update(
                "DELETE FROM products WHERE id = :id",
                new MapSqlParameterSource().addValue("id", prod.getId()));
        logger.info(count + " rows were deleted");
    

    public List<Product> retrieveProduct(int id) 
        List<Product> products = getSimpleJdbcTemplate().query(
                "select id, description, price from products where id = :id",
                new ProductMapper(),
                new MapSqlParameterSource().addValue("id", id));
        if (products.size() == 0)
            return null;
        else
            products.get(id);
        return products;
    

    public Product createProduct(Product p) 
        logger.info("Creating product: " + p.getDescription() + " Price:"
                + p.getPrice());

        int count = getSimpleJdbcTemplate()
                .update("INSERT INTO products (description,price,id) VALUES (:description, :price,:id)",
                        new MapSqlParameterSource()
                                .addValue("description", p.getDescription())
                                .addValue("price", p.getPrice())
                                .addValue("id", p.getId()));

        logger.info("Rows inserted: " + count);

        return p;
    

    /** Logger for this class and subclasses */
    protected final Log logger = LogFactory.getLog(getClass());

    public List<Product> getProductList() 
        logger.info("Getting products!");
        List<Product> products = getSimpleJdbcTemplate().query(
                "select id, description, price from products",
                new ProductMapper());
        return products;
    

    public void saveProduct(Product prod) 
        logger.info("Saving product: " + prod.getDescription());
        int count = getSimpleJdbcTemplate()
                .update("update products set description = :description, price = :price where id = :id",
                        new MapSqlParameterSource()
                                .addValue("description", prod.getDescription())
                                .addValue("price", prod.getPrice())
                                .addValue("id", prod.getId()));
        logger.info("Rows affected: " + count);
    

    private static class ProductMapper implements
            ParameterizedRowMapper<Product> 

        public Product mapRow(ResultSet rs, int rowNum) throws SQLException 
            Product prod = new Product();
            prod.setId(rs.getInt("id"));
            prod.setDescription(rs.getString("description"));
            prod.setPrice(new Double(rs.getDouble("price")));
            return prod;
        

    


我很困惑,尝试了所有方法但没有用。任何人都可以帮忙吗?谢谢

【问题讨论】:

【参考方案1】:

它的工作!

我已经设法使用 Spring 2.5、Spring security 2.0.4 和 HSQLDB 来同时工作(使用数据库进行安全集成的 MVC 应用程序)。我在这里所做的是在我的 dataSourcePopulator 文件中添加:HsqldbSchemaAndDataPopulator.java 以下行用于填充产品:

template
.execute("CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,"
+ "PASSWORD VARCHAR_IGNORECASE(50) NOT NULL,"
+ "ENABLED BOOLEAN NOT NULL);");
//some dummy items
template
.execute("INSERT INTO products (id, description, price) values(1, 'Lamp', 5.78);");
template
.execute("INSERT INTO products (id, description, price) values(2, 'Table', 75.29);");
template
.execute("INSERT INTO products (id, description, price) values(3, 'Chair', 22.81);");

及其工作。

【讨论】:

以上是关于HSQLDB 问题:使用 HSQL 作为使用 JDBC 模板的现有 MVC 应用程序的后端的主要内容,如果未能解决你的问题,请参考以下文章

HSQL系统内存使用量增加

Weblogic 中的 HSQL 配置

使用UTF-8编码导出HSQLDB数据库

使用 HSQL 时出错 - 2.2

无法使用休眠插入 hsql 数据库

HSQL可视化工具