如果在代码片段之后entity.getHistory()为null:
(getEntityManager()返回弹簧注入的EntityManager,数据库字段历史记录类型为:text或varchar2(2000)
Query query = getEntityManager().createNativeQuery("insert into table_name(..., history, ....) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
[...]
.setParameter(6, entity.getHistory())
[...]
query.executeUpdate();
给出奇怪的例外:
17/11/11 06:26:09:009 [pool-2-thread-1] WARN util.JDBCExceptionReporter:100 - SQL Error: 0, SQLState: 42804
17/11/11 06:26:09:009 [pool-2-thread-1] ERROR util.JDBCExceptionReporter:101 - ERROR: **column "history" is of type text but expression is of type bytea**
提示:您需要重写或转换表达式。
仅在此配置中出现问题:
操作系统:CentOS 5.6版(最终版)
Java:1.6.0_26
DB:PostgreSQL 8.1
JDBC驱动程序:postgresql-9.1-901.jdbc4
Application Server:apache-tomcat-6.0.28
在其他一些配置或历史记录为空字符串时,一切正常。 从pgAdmin执行的相同语句工作正常。
我猜问题是在PostgreSQL JDBC驱动程序中,是否有一些明智的理由将空字符串视为bytea值? Postgres 8和9之间可能有一些奇怪的变化吗?
答案 0 :(得分:5)
有一个简单的修复:当你构建查询字符串时,如果参数为null - 使用“null”而不是“?”。
正如@araqnid所说,Hibernate错误地将null值转换为bytea类型,因为它不知道更好。
答案 1 :(得分:4)
由于您使用空值调用setParameter(int,Object)
,因此猜测实体管理器不知道用于绑定参数的持久性类型。 Istr Hibernate倾向于使用SerializableType,它等同于bytea。
您可以使用带有Parameter对象的setParameter方法,这样您可以指定类型吗?我还没有真正使用过JPA,所以无法给出详细的指针。
(恕我直言,这是你滥用EntityManager的native-sql查询接口进行插入,而不是实际映射实体,或只是直接进入JDBC)的唯一甜点。
答案 2 :(得分:2)
使用Hibernate特定的Session API可以解决此问题:
String sql = "INSERT INTO person (id, name) VALUES (:id, :name)";
Session session = em.unwrap(Session.class);
SQLQuery insert = session.createSQLQuery(sql);
sql.setInteger("id", 123);
sql.setString("name", null);
insert.executeUpdate();
我还提交HHH-9165报告此问题,如果它确实是个错误。
答案 3 :(得分:1)
如果您愿意使用PreparedStatement类而不是Query:
if (entity.getHistory() == null)
stmt.setNull(6, Types.VARCHAR);
else
stmt.setString(6, entity.getHistory());
(在您的查询字符串中使用?::text
可能也有效,但我自己从未这样做过。)
答案 4 :(得分:1)
您可以在查询中将参数转换为适当的类型。我认为该解决方案也应该适用于其他数据库。
之前:
@Query("SELECT person FROM people person"
+ " WHERE (?1 IS NULL OR person.name = ?1)")
List<Person> getPeopleWithName(final String name);
之后:
@Query("SELECT person FROM people person"
+ " WHERE (?1 IS NULL OR person.name = cast(?1 as string))")
List<Person> getPeopleWithName(final String name);
也可用于LIKE
语句:
person.name LIKE concat('%', cast(?1 as string), '%')
并带有数字(此处为Double
类型):
person.height >= cast(cast(?1 as string) as double)
答案 5 :(得分:0)
带有sql type参数的JDBC setNull是未通过JDBC驱动程序测试套件的旧JDBC驱动程序的后备。
可以防止查询中出现空错误,如下所示:
SELECT FROM FROM a WHERE:lastName IS NULL OR LOWER(a.lastName)=:lastName
在修复此issue后,这应该适用于Postgresql。
答案 6 :(得分:0)
以上大多数答案都很有意义,有助于我缩小问题范围。
我修复了以下null的问题:
setParameter(8, getDate(), TemporalType.DATE);
答案 7 :(得分:0)
在我的springboot应用程序中使用postgres和hibernate出现了此问题。 我需要提供从/到参数的日期,每种组合都可能包含空值。
查询摘录:
drop table if exists t;
create table t
(id int,status varchar(20), data varchar(3),date varchar(10));
insert into t values
( 1 , 'START' , 'a4c' , 'Jan 1'),
( 2 , 'WORKING' , '2w3' , 'Dec 29'),
( 3 , 'WORKING' , '2d3' , 'Dec 29'),
( 4 , 'WORKING' , '3ew' , 'Dec 26'),
( 5 , 'WORKING' , '5r5' , 'Dec 23'),
( 6 , 'START' , '2q3' , 'Dec 22'),
( 7 , 'WORKING' , '32w' , 'Dec 20'),
( 8 , 'WORKING' , '9k5' , 'Dec 10');
SELECT MIN(ID) ID,
'START' STATUS,
SUM(CASE WHEN STATUS <> 'START' THEN 1 ELSE 0 END) AS OBS,
Max(DATE) DATE
FROM
(
select t.*,
CASE WHEN STATUS = 'START' THEN DATE ELSE '' END AS DT,
COALESCE(
(select t1.id from t t1 where t1.STATUS = 'START' and t1.id > t.id ORDER BY T1.ID limit 1)
,99999) NEXTID
from t
) S
GROUP BY NEXTID;
+------+--------+------+--------+
| ID | STATUS | OBS | DATE |
+------+--------+------+--------+
| 1 | START | 4 | Jan 1 |
| 6 | START | 2 | Dec 22 |
+------+--------+------+--------+
2 rows in set (0.00 sec)
道电话:
...
WHERE f.idf = :idCat
AND f.supplier = TRUE
AND COALESCE (pc.datefrom, CAST('2000-1-1' AS DATE) ) <= COALESCE (:datefrom, now())
AND COALESCE (pc.dateto, CAST('2200-12-31' AS DATE) ) >= COALESCE (:dateto, now())
答案 8 :(得分:0)
我在使用Oracle数据库执行UPDATE时遇到相同的问题。 有时,一些要更新的字段为空,并且会发生此问题。显然,如本主题中所述,JPA正在将我的空值投射到bytea中。
我放弃使用Query对象更新表并使用EntityManager.merge(Entity)方法。
我只创建带有所有信息的Entity对象,当我执行merge(Entity)时,JPA执行SELECT,将已经存在数据库中的信息与我的Entity对象进行比较,并正确执行UPDATE。也就是说,JPA为空的Entity变量创建一个“ field = NULL”语句。