Hibernate操作MySQL使用reserved word引发错误: “You have an error in your SQL syntax; check the manual that co...

本文记录了在使用Hibernate4.0向MySQL5数据库插入Entity时遇到的SQL语法错误,并详细介绍了通过科学方法逐步排查并解决问题的过程。最终发现问题是由于字段名与MySQL保留字冲突导致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天利用Hibernate4.0上往MySQL 5数据库插入一个Entity时,一直出现以下的错误:

 

You have an error in your SQL syntax; check the manual thatcorresponds to your MySQL server version for the right syntax to user near `show, sid) value

 

一直觉得不应该啊,怎么会呢,不可能啊,自己就是在想这些无用的东西,也尝试了好多次,感觉都是徒劳,后来采取科学的解决步骤来逐步地一点一滴地循序渐进地找到解决方法,其实后来证明虽然一步一步来,看起来慢,但这毕竟是一条科学的方法,只要沿着这条道路往前走,离正确的答案只会越来越近的,肯定会迅速发现问题的所在的。这其中,我觉得排除法是一个很好的方法,例如我要插入这个Entity不成功,那我就把这个Entity的其他attribute先去掉,只保留一个attribute,然后看能否insert成功;然后逐步加入其它的attribute,直到一个attribute被加进去以后,引发了上述错误,这样我们就能够迅速地确定到底是哪一个attribute引发了上述错误,很快地找到问题的根源,有的放矢。

 

事实证明,开始漫无目的方法花费了一天时间都没能找到正确的解决方法,而按照后一种方法,很快就找到问题的原因(加入show这个attribute后开始出错)。下面针对此问题开始分析问题原因。

 

Hibernate 定义:

@Column(nullable = false)
private boolean
show;

 

MySQL中定义是这样的:

Show bit(1) not null

 

一种可能是因为MySQL中的bit datatype和JAVA中的boolean不能正确转换,stackoverflow中有个类似的问题如下:

Causedby: org.hibernate.HibernateException:
Wrong column type in PUBLIC.PUBLIC.EVENT for column Checked. Found: bit,expected: boolean

 

I worked this out by adding columnDefinition = "BIT" to the@Column line.


@Column(name = "B", columnDefinition = "BIT", length =1)
public boolean isB() {
   
return b;
}

Its defined as a'BIT(1)' in the DB as well. Also worked with TINYINT. This is the easiestsolution I've found since the change is super-minor and no need to touch theDB.

Using: MySQL Server5.5.13, Hibernate 4.1.1, JDK 1.6

 

我按照以上的思路,改造了我的show属性,可是还是不成功,由此可见,我的问题只是与上面这个问题相似,但不是由以上原因引起的。还有一些人建议should not use BIT columns in MySQL,建议使用tinyint,但也不是问题的主要原因。

 

应该是show属性引起的,继续google,还是stackoverflow中有人碰到类似的问题,解决方法如下:

Ithink the problem is that ORDER is aMySQL reserved word.

To get the INSERTstatement to execute, you'd need to have that column name enclosed inbackticks, like this:

insert into folder (folder_name, `order`) values (?,?)

 

OKI've found solution; we still can use 'order'keyword as column name like this:

@Column(name = "`order`", length = 10,precision =0)
private int order;

 

 

好吧,既然order是MySQL的reserved word,那show也很有可能,果然改成其他名称后立即得到解决:

@Column(name = "label_show", nullable = false)
private boolean
show;

 

查阅MySQL 官方文档,可以得到Reserved Words in MySQL:

Table 2.1. Reserved Words in MySQL 5.0

ADD

ALL

ALTER

ANALYZE

AND

AS

ASC

ASENSITIVE

BEFORE

BETWEEN

BIGINT

BINARY

BLOB

BOTH

BY

CALL

CASCADE

CASE

CHANGE

CHAR

CHARACTER

CHECK

COLLATE

COLUMN

CONDITION

CONNECTION[a]

CONSTRAINT

CONTINUE

CONVERT

CREATE

CROSS

CURRENT_DATE

CURRENT_TIME

CURRENT_TIMESTAMP

CURRENT_USER

CURSOR

DATABASE

DATABASES

DAY_HOUR

DAY_MICROSECOND

DAY_MINUTE

DAY_SECOND

DEC

DECIMAL

DECLARE

DEFAULT

DELAYED

DELETE

DESC

DESCRIBE

DETERMINISTIC

DISTINCT

DISTINCTROW

DIV

DOUBLE

DROP

DUAL

EACH

ELSE

ELSEIF

ENCLOSED

ESCAPED

EXISTS

EXIT

EXPLAIN

FALSE

FETCH

FLOAT

FLOAT4

FLOAT8

FOR

FORCE

FOREIGN

FROM

FULLTEXT

GOTO[b]

GRANT

GROUP

HAVING

HIGH_PRIORITY

HOUR_MICROSECOND

HOUR_MINUTE

HOUR_SECOND

IF

IGNORE

IN

INDEX

INFILE

INNER

INOUT

INSENSITIVE

INSERT

INT

INT1

INT2

INT3

INT4

INT8

INTEGER

INTERVAL

INTO

IS

ITERATE

JOIN

KEY

KEYS

KILL

LABEL[c]

LEADING

LEAVE

LEFT

LIKE

LIMIT

LINES

LOAD

LOCALTIME

LOCALTIMESTAMP

LOCK

LONG

LONGBLOB

LONGTEXT

LOOP

LOW_PRIORITY

MATCH

MEDIUMBLOB

MEDIUMINT

MEDIUMTEXT

MIDDLEINT

MINUTE_MICROSECOND

MINUTE_SECOND

MOD

MODIFIES

NATURAL

NOT

NO_WRITE_TO_BINLOG

NULL

NUMERIC

ON

OPTIMIZE

OPTION

OPTIONALLY

OR

ORDER

OUT

OUTER

OUTFILE

PRECISION

PRIMARY

PROCEDURE

PURGE

READ

READS

REAL

REFERENCES

REGEXP

RELEASE

RENAME

REPEAT

REPLACE

REQUIRE

RESTRICT

RETURN

REVOKE

RIGHT

RLIKE

SCHEMA

SCHEMAS

SECOND_MICROSECOND

SELECT

SENSITIVE

SEPARATOR

SET

SHOW

SMALLINT

SONAME

SPATIAL

SPECIFIC

SQL

SQLEXCEPTION

SQLSTATE

SQLWARNING

SQL_BIG_RESULT

SQL_CALC_FOUND_ROWS

SQL_SMALL_RESULT

SSL

STARTING

STRAIGHT_JOIN

TABLE

TERMINATED

THEN

TINYBLOB

TINYINT

TINYTEXT

TO

TRAILING

TRIGGER

TRUE

UNDO

UNION

UNIQUE

UNLOCK

UNSIGNED

UPDATE

UPGRADE[d]

USAGE

USE

USING

UTC_DATE

UTC_TIME

UTC_TIMESTAMP

VALUES

VARBINARY

VARCHAR

VARCHARACTER

VARYING

WHEN

WHERE

WHILE

WITH

WRITE

XOR

YEAR_MONTH

ZEROFILL

 

 

 

来自 <http://dev.mysql.com/doc/mysqld-version-reference/en/mysqld-version-reference-reservedwords-5-0.html>

转载于:https://www.cnblogs.com/mewishu/p/4162845.html

### 解决 `java.sql.SQLSyntaxErrorException` 的方法 当遇到 `java.sql.SQLSyntaxErrorException` 时,这意味着发送给MySQL服务器的SQL命令存在语法错误。为了有效地解决问题,可以采取以下几个方面的方法: #### 检查SQL语句中的关键字和拼写 确保所有的SQL关键词都按照MySQL的标准书写,并且注意大小写的敏感性。例如,在构建查询字符串时,避免遗漏表名或字段名前后的反引号(如果适用),这有助于防止因保留字冲突而引发的问题[^1]。 #### 验证SQL语句结构 仔细审查SQL语句的整体结构,特别是复杂的嵌套子查询或是带有特殊操作符的情况。对于像 `WHERE`, `JOIN`, 或者其他可能导致混淆的地方要格外小心。上述提到的例子中,“near 'WHERE name = 'John''”暗示可能是在尝试在一个不允许的位置使用了 `WHERE` 子句,或者是之前的部分已经包含了非法字符或格式[^2]。 #### 使用参数化查询来预防注入攻击并简化调试 通过采用预编译语句 (PreparedStatement),不仅可以提高安全性还可以减少手动生成SQL串带来的潜在风险。这样做的好处之一就是能够自动处理转义字符等问题,从而降低发生此类异常的可能性。下面是一个简单的例子展示如何利用 PreparedStatement 来执行更新操作而不必担心SQL注入的风险: ```java String sql = "UPDATE users SET age=? WHERE id=?"; try { PreparedStatement pstmt = connection.prepareStatement(sql); pstmt.setInt(1, user.getAge()); pstmt.setLong(2, user.getId()); int affectedRows = pstmt.executeUpdate(); } catch (SQLException e) { // Handle exceptions here... } ``` #### 审视MyBatis配置文件 如果是基于框架的应用程序,则还需要确认映射器XML或其他形式的数据访问层定义是否正确无误。有时候问题并不在于实际的SQL本身而是来自于这些地方设置不当所引起的间接影响。比如在 MyBatis 中,应该确保 `<select>`, `<insert>` 等标签内的属性值以及动态SQL部分均符合预期[^3]. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值