【问题标题】:MySQLSyntaxErrorException while attempting to persist blob with hibernateMySQLSyntaxErrorException 尝试使用休眠状态持久化 blob
【发布时间】:2012-10-25 10:43:57
【问题描述】:

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

我已经尝试过使用 session.save(object); 或将 byte[] 替换为 Blob。结果还是一样。我发现的所有工作示例都使用完全不同的方法 - 例如他们使用 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

beans.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.properties:

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 引擎。

Update.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 配置有关。

【问题讨论】:

  • 可以包含生成的sql查询吗?
  • 目前我有很多任务要做,所以我能找到的最好的是:Hibernate: insert into updates (changelog, added, developmentVersion, filedata, filedataType, major, minor, nightly, release, package, type, uploader, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - 不幸的是,在我需要移动之前,我没有设法将 Spring 配置为显示完整的 SQL继续执行具有更高优先级的任务,而准备好的语句 (?) 根本没有帮助。
  • 我更新了问题,添加了一些我可以找到的信息。
  • 数据库中filedata 的实际类型是什么?例如,它真的是BLOB 还是varbinary
  • 在数据库中,该字段定义为LONGBLOB。有没有可能会很大?这会导致 syntax 错误吗?

标签: mysql hibernate jpa spring-mvc blob


【解决方案1】:

感谢一位开发人员的帮助,我发现了问题所在:我使用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

我想我以后在选择列名时必须更加小心。希望对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多