Spring MVC、Hibernate4、および MySQL5 を使用して簡単な Web ページを作成しています。私が使用するモデルの 1 つに BLOB 値 (byte[]) が含まれています。そのモデルを永続化しようとするとentityManager.persist()
、MySQLSytnaxException が発生します。実際には、 @Transactional アノテーションを無視した永続化/マージ/削除など、現在の構成にはさらに問題がありますが、これが最も重要です。
session.save(object);
byte[] をBlobで使用または置換しようとしました。それでも同じ結果です。私が見つけたすべての実用的な例は、完全に異なるアプローチを使用しています-たとえば、JPAの代わりに HibernateSessionManager と HibernateTransactionManager を使用しています-エンティティを永続化する方法を完全に変更する必要のないソリューションを見つけたいと思います。役立つだろう。
コード/構成/仮定でどのような間違いを犯したか教えていただけますか?
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.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 構成に関連している可能性が高いため、Hibernate.properties コンテンツも追加しました。