引起:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:表' test.spring_session'不存在 - Spring Boot

时间:2016-08-29 16:57:23

标签: spring spring-boot spring-jdbc

我正在开发springboot-springsession-jdbc-demo。当我只是运行代码时,我得到以下错误。它看起来我需要在application.properties中设置一些属性,以便事先创建模式/表。必需的配置已经放置,但仍然会出错。代码存在于https://github.com/sivaprasadreddy/spring-session-samples

参考错误:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [DELETE FROM SPRING_SESSION WHERE LAST_ACCESS_TIME < ?]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'test.spring_session' doesn't exist
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:870) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:931) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:941) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.session.jdbc.JdbcOperationsSessionRepository$6.doInTransaction(JdbcOperationsSessionRepository.java:481) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.session.jdbc.JdbcOperationsSessionRepository$6.doInTransaction(JdbcOperationsSessionRepository.java:478) ~[spring-session-1.2.1.RELEASE.jar:na]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.session.jdbc.JdbcOperationsSessionRepository.cleanUpExpiredSessions(JdbcOperationsSessionRepository.java:478) ~[spring-session-1.2.1.RELEASE.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_45]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_45]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_45]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_45]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_45]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_45]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'test.spring_session' doesn't exist
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_45]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_45]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_45]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422) ~[na:1.8.0_45]
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:404) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.Util.getInstance(Util.java:387) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:942) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3966) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3902) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2526) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2673) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5098) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994) ~[mysql-connector-java-5.1.39.jar:5.1.39]
    at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:877) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:870) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633) ~[spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    ... 21 common frames omitted

的pom.xml

    <!-- Parent pom providing dependency and plugin management for applications 
        built with Maven -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>


    <dependencies>
        <!-- Spring Boot Starter Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Spring Boot Starter JDBC -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Spring Boot Starter Thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- Spring Session -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session</artifactId>
        </dependency>


        <!-- Spring Boot devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- MYSQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- H2 DB -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
    </dependencies>
</project>

Application.java

@SpringBootApplication
@EnableJdbcHttpSession
@EnableAutoConfiguration
public class Application{
    public static void main(String[] args){
        SpringApplication.run(Application.class, args);
    }
}

HomeController.java

@Controller
public class HomeController {
    private static final AtomicInteger UserId = new AtomicInteger(0);

    @RequestMapping("/")
    public String home(Model model){
        return "index";
    }

    @RequestMapping("/add-simple-attrs")
    public String handleSimpleSessionAttributes(HttpServletRequest req, HttpServletResponse resp){
        String attributeName = req.getParameter("attributeName");
        String attributeValue = req.getParameter("attributeValue");

        req.getSession().setAttribute(attributeName, attributeValue);

        User user = new User();
        user.setName(attributeValue);

        req.getSession().setAttribute(attributeName, user);
        return "redirect:/";
    }


    @RequestMapping("/add-object-attrs")
    public String handleObjectSessionAttributes(HttpServletRequest req, HttpServletResponse resp){
        String name = req.getParameter("name");
        User user = new User();

        user.setId(UserId.incrementAndGet());
        user.setName(name);

        req.getSession().setAttribute("USER_ID_"+user.getId(), user);
        return "redirect:/";
    }
}

User.java

public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    private Integer id;
    private String name;

    public User(){

    }

    public User(Integer id, String name){
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + "]";
    }

    public Integer getId(){
        return id;
    }

    public void setId(Integer id){
        this.id = id;
    }

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name;
    }
}

application.properties

logging.level.org.springframework=INFO

    ################### DataSource Configuration ##########################
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/test
    spring.datasource.username=root
    spring.datasource.password=root

    spring.datasource.initialize=true
    #spring.datasource.data=classpath:org/springframework/session/jdbc/schema-h2.sql
    spring.datasource.data=classpath:org/springframework/session/jdbc/schema-mysql.sql
    spring.datasource.continue-on-error=true
    spring.jpa.hibernate.ddl-auto=create
    #spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

的index.html

 <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" 
          xmlns:th="http://www.thymeleaf.org">
    <head>
    <meta charset="utf-8"/>
    <title>Home</title>
    </head>
    <body>
        <h2 th:text="#{app.title}">App Title</h2>

        <h4>Add Simple Attributes To Session</h4>
        <form class="form-inline" role="form" action="add-simple-attrs" method="post">
            <label for="attributeName">Attribute Name</label>
            <input id="attributeName" type="text" name="attributeName"/>
            <label for="attributeValue">Attribute Value</label>
            <input id="attributeValue" type="text" name="attributeValue"/>
            <input type="submit" value="Set Attribute"/>
        </form>

        <h4>Add Object Attributes To Session</h4>
        <form class="form-inline" role="form" action="add-object-attrs" method="post">
            <label for="name">User Name</label>
            <input id="name" type="text" name="name"/>
            <input type="submit" value="Save"/>
        </form>


        <h3>Session Attributes</h3>
        <table>
            <thead>
                <tr>
                    <th>Attribute Name</th>
                    <th>Attribute Value</th>
                </tr>
            </thead>
            <tbody>
                <tr th:each="attr : ${session}">
                    <td th:text="${attr.key}">Name</td>
                    <td th:text="${attr.value}">Value</td>
                </tr>
            </tbody>
        </table>
    </body>
    </html>

3 个答案:

答案 0 :(得分:6)

当使用Spring-boot 2.0.5(与OP使用的1.4.0相对)和Postgres驱动程序时,我有一个非常相似的错误:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [DELETE FROM spring_sessions WHERE EXPIRY_TIME < ?]; nested exception is org.postgresql.u
til.PSQLException: ERROR: relation "spring_sessions" does not exist
  Position: 13
        at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:234) ~[spring-jdbc-5.0.8.RELEASE.jar!/:5.0.8.RELEA
SE]
        // redacted...
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
Caused by: org.postgresql.util.PSQLException: ERROR: relation "spring_sessions" does not exist
  Position: 13
        at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2433) ~[postgresql-42.2.2.jar!/:42.2.2]
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2178) ~[postgresql-42.2.2.jar!/:42.2.2]
        // redacted...
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:605) ~[spring-jdbc-5.0.8.RELEASE.jar!/:5.0.8.RELEASE]
        ... 16 common frames omitted

根据documentation,设置由关系数据库支持的Spring Session就像向您的application.properties添加单个配置属性一样简单:

spring.session.store-type=jdbc

请注意,为了自动创建会话表,我还必须指定:

spring.session.jdbc.initialize-schema=always

一旦指定了此设置,Spring就会使用spring-session-jdbc jar中正确的SQL初始化脚本。我的错误是没有指定该选项-在这种情况下,embedded被用作默认值。

答案 1 :(得分:1)

我不确定这是否是最好的解决方案(甚至是我刚接触弹簧的解决方案,也不知道这样做的后果),但是我遇到了同样的问题,设法删除了解决方案注释@EnableJdbcHttpSession

根据韦德兰·帕维奇(Vedran Pavic):

  

spring.session。*对您不起作用的原因是因为您   使用@EnableJdbcHttpSession。这意味着您正在配置   Spring Session是明确的,因此Spring Boot会回退其   自动配置。

     

您应该删除@EnableJdbcHttpSession并确保Spring Boot是   自动配置Spring Session。此外,您也可以离开   spring.session.store-type出来,因为Spring Boot应该能够   推断您正在使用哪种会话存储库实现   因为您在上只有SessionRepository实现   classpath(即您仅依赖spring-session-jdbc而没有其他依赖   Spring Session模块)。

Original Post

这将解决您眼前的问题,但是我不确定是否会破坏其他东西...

答案 2 :(得分:0)

我认为您有多个问题默认情况下,jdbc具有H2数据库。它是由spring自动创建的。 检查它是否在那里。因此,首先在H2上运行它。然后将相同的数据库和表复制到MySQL。创建与MySQL相同的架构和表,然后更改与MySQL的连接。

Spring Boot自动创建一个数据源,该数据源将Spring Session连接到H2数据库的嵌入式实例 src / main / resources / application.properties

spring.datasource.url= # JDBC URL of the database.
spring.datasource.username= # Login username of the database.
spring.datasource.password= # Login password of the database.

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root