1

我正在使用 Spring MVC、Hibernate4 和 MySQL5 创建一些简单的网页。我使用的模型之一包含 BLOB 值(字节 [])。当我尝试使用该模型持久化时,entityManager.persist() 我得到 MySQLSytnaxException。实际上当前配置还有更多问题,例如忽略@Transactional注解的persist/merge/remove,但这是最关键的。

我已经尝试session.save(object);通过 Blob 使用或替换 byte[]。结果还是一样。我发现的所有工作示例都使用完全不同的方法 - 例如,它们使用 HibernateSessionManager 和 HibernateTransactionManager 而不是 JPA 的 - 当我仍然不确定时,我想找到不需要完全改变我持久实体的解决方案有助于。

你能告诉我我在代码/配置/假设中犯了什么错误吗?

堆栈跟踪的开始以及 Hibernate 跟踪:

Hibernate: 
        insert 
        into
            updates
            (changelog, added, developmentVersion, filedata, filedataType, major, minor, nightly, release, package, type, uploader, id) 
        values
            (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
22:53:10,888 TRACE BasicBinder:83 - binding parameter [1] as [VARCHAR] - sdfsd
22:53:10,891 TRACE BasicBinder:71 - binding parameter [2] as [DATE] - <null>
22:53:10,894 TRACE BasicBinder:83 - binding parameter [3] as [BOOLEAN] - false
22:53:10,898 TRACE BasicBinder:83 - binding parameter [4] as [BLOB] - javax.sql.rowset.serial.SerialBlob@298fd36c
22:53:10,924 TRACE BasicBinder:83 - binding parameter [5] as [VARCHAR] - image/png
22:53:10,926 TRACE BasicBinder:83 - binding parameter [6] as [INTEGER] - 1
22:53:10,928 TRACE BasicBinder:83 - binding parameter [7] as [INTEGER] - 0
22:53:10,935 TRACE BasicBinder:83 - binding parameter [8] as [INTEGER] - 0
22:53:10,936 TRACE BasicBinder:83 - binding parameter [9] as [INTEGER] - 0
22:53:10,939 TRACE BasicBinder:83 - binding parameter [10] as [INTEGER] - 36
22:53:10,941 TRACE EnumType:292 - Binding {0} to parameter: {1}
22:53:10,944 TRACE BasicBinder:83 - binding parameter [12] as [INTEGER] - 18
22:53:10,955 TRACE BasicBinder:83 - binding parameter [13] as [INTEGER] - 0
22:53:10,998  WARN SqlExceptionHelper:143 - SQL Error: 1064, SQLState: 42000
22:53:10,999 ERROR SqlExceptionHelper:144 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'release, package, type, uploader, id) values ('sdfsd', null, 0, _binary'‰PNG
' at line 1
22:53:11,027  INFO AbstractBatchImpl:195 - HHH000010: On release of batch it still contained JDBC statements
Nov 07, 2012 10:53:11 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [repoApplication] in context with path [/server] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'release, package, type, uploader, id) values ('sdfsd', null, 0, _binary'‰PNG
' at line 1; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'release, package, type, uploader, id) values ('sdfsd', null, 0, _binary'‰PNG
' at line 1] with root cause
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'release, package, type, uploader, id) values ('sdfsd', null, 0, _binary'‰PNG
' at line 1

豆类.xml:

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

    ...

    <!-- Hibernate configuration -->    

    <!-- Specifies dataSource object managing connections to database -->  
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName" value="${database.driver}" /> 
        <property name="url" value="${database.url}" /> 
        <property name="username" value="${database.user}" /> 
        <property name="password" value="${database.password}" />
    </bean>

    <!-- Defines SessionFactory -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        ...
        <property name="hibernateProperties">
            <util:properties location="classpath:Hibernate.properties" />
        </property>
    </bean>

    <!-- Defines TransactionManager -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- Binds TransactionManager to annotations -->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- Enables Spring annotations -->
    <context:annotation-config />

    ...

</beans>

休眠.属性:

hibernate.database         =MYSQL
hibernate.dialect          =org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql         =true
hibernate.format_sql       =true
hibernate.use_sql_comments =true
hibernate.hbm2ddl.auto     =update

MySQL 数据库中的所有表都使用 InnoDB 引擎。

更新.java(模型):

import java.sql.Blob;
import java.sql.Date;
import java.sql.SQLException;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.sql.rowset.serial.SerialBlob;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.Type;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

...

@Entity
@Table(name = "updates")
@VersionNumberCorrect
public class Update {
    @Id
    @Column(name = "id", unique = true)
    private int id;

    @NotNull
    @ManyToOne
    @JoinColumn(name = "package")
    private Package thePackage;

    @NotNull
    @ManyToOne
    @JoinColumn(name = "uploader")
    private User uploader;

    @Column(name = "added")
    private Date date;

    @Column(name = "changelog")
    @NotNull
    @NotEmpty
    private String changelog;

    @Column(name = "major")
    private int major;

    @Column(name = "minor")
    private int minor;

    @Column(name = "release")
    private int release;

    @Column(name = "nightly")
    private int nightly;

    @Column(name = "developmentVersion")
    private boolean developmentVersion;

    @Column(name = "type")
    @Enumerated(EnumType.ORDINAL)
    private EUpdateStrategy type;

    @Column(name = "filedata")
    @Lob
    @Type(type = "blob")
    @NotNull
    private Blob filedata;

    @Column(name = "filedataType")
    private String filedataType;

    public Update() {
    }

    ...
}

UpdateServiceImp.java(服务):

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

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

...

@Service
@Transactional
public class UpdateServiceImp implements UpdateService {
    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public void persist(Update update) {
        getSession().persist(update);
    }

    @Override
    public Update merge(Update update) {
        return (Update) getSession().merge(update);
    }

    @Override
    public void remove(Update update) {
        getSession().delete(update);
    }

    ...

    /**
     * Returns new Session instance.
     * 
     * @return new Session
     */
    private Session getSession() {
        return sessionFactory.getCurrentSession();
    }
}

编辑:我将 EntityManagerManager 的用法更改为 Hibernate 的 SessionFactory - 我试图改变这种想法,它可能会有所帮助。它没有,但是代码变得更干净了:)。我从 Hibernate 日志中添加了一些可能有用的信息。我还添加了 Hibernate.properties 内容,因为这个错误很可能与 Hibernate 配置有关。

4

1 回答 1

6

感谢一位开发人员的帮助,我发现了问题所在:我正在使用release其中一个属性的名称。我发现这release是 MySQL 中的一个关键字,当它出现在查询中时,它会使语法无效。

老实说,得知 Hibernate 不会在列、模式和表的名称中使用撇号,我真的很惊讶。我认为以这种方式编写 SQL 是一种常见的做法:

INSERT INTO `mySqlTable` VALUES (null, 'value') ;

或者

INSERT INTO 'dbo'.'msSqlTable' VALUES (null, 'value');

但是 Hibernate 会这样做:

INSERT INTO mySqlTable VALUES (null, 'value') ;

对于 MySQL5,保留字列表很长:http ://dev.mysql.com/doc/refman/5.0/en/reserved-words.html

我想我将来在选择列名时必须更加小心。希望这会帮助某人。

于 2012-11-08T10:03:37.100 回答