The database returned no natively generated identity value

近日,在将一个基于jsf+seam+hibernate+db2的应用部署到jboss上时,出现这么一个报错

org.hibernate.HibernateException: The database returned no natively generated identity value

症状:可以select,update和delete,不能insert,insert就报上面这个错,id的生成有问题。

到网上搜索解决方法,都是说这是数据库中表的id没有设置自增引起的。可是我的数据库中表的id都设置了自增,为何也报这个错误呢?

跟踪代码发现Hibernate从insert语句的PreparedStatement.getGeneratedKeys()方法返回的ResultSet中获取生成的id,但没有获取到,报了这么个错误。

分析一下,报这个错,可能的原因有三:数据库的原因,JDBC driver的原因,hibernate的原因。

数据库的原因应该就是网上大部分人遇到的id自增长的问题,不过我这里不存在这个问题。

JDBC driver的原因,有可能,尝试换一个驱动试试看,可是没找到。。。。

hibernate呢?考虑到使用的jboss自带的hibernate,于是使用最新的稳定版本替换了一下,还是不行。。。

被该问题困扰整日,次日再搜索相关资料时,偶然发现一个hibernate jbdc的属性hibernate.jdbc.use_get_generated_keys,其介绍如下:

Enables use of JDBC3 PreparedStatement.getGeneratedKeys() to retrieve natively generated keys after insert.
Requires JDBC3+ driver and JRE1.4+, set to false if your driver has problems with the Hibernate identifier generators. By
default, it tries to determine the driver capabilities using connection metadata.
e.g. true|false

顿时灵光一闪,感觉找到了打开通向光明之门的金钥匙。

于是在persistence.xml中添加该属性的设置

<property name="hibernate.jdbc.use_get_generated_keys" value="false"/>

再一deploy,万事OK。

再次跟踪代码,发现原来通过该参数的设置,可以将id的获取委派到不同的类:

public InsertGeneratedIdentifierDelegate getInsertGeneratedIdentifierDelegate(
	PostInsertIdentityPersister persister,
        Dialect dialect,
        boolean isGetGeneratedKeysEnabled) throws HibernateException {
	if ( isGetGeneratedKeysEnabled ) {
		return new GetGeneratedKeysDelegate( persister, dialect );
	}
	else if ( dialect.supportsInsertSelectIdentity() ) {
		return new InsertSelectDelegate( persister, dialect );
	}
	else {
		return new BasicDelegate( persister, dialect );
	}
}

hibernate.jdbc.use_get_generated_keys=true时,委派到GetGeneratedKeysDelegate,但该类的相关方法没搞定;

hibernate.jdbc.use_get_generated_keys=false时,这里委派到了 BasicDelegate,该类通过DB2Dialect的getIdentitySelectString()即使用db2的方言“values identity_val_local()”成功获取id。

参考:Hibernate JDBC and Connection Properties

Tags: db2, Hibernate, jboss

This entry was posted on Tuesday, April 6th, 2010 at 4:36 pm and is filed under Hibernate. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
由于给定引用内容未涉及“Promote方法在分布式事务中返回无效值的解决方案”相关信息,以下是一般性的分析与可能的解决方案。 在分布式事务中,Promote方法返回无效值可能由多种原因导致。网络问题可能使请求无法正常传输或响应丢失,数据库故障会影响数据的读写,代码逻辑错误也可能造成返回值异常。 针对网络问题,可以通过重试机制来解决。当检测到Promote方法返回无效值时,进行有限次数的重试。以下是Python的示例代码: ```python import time MAX_RETRIES = 3 RETRY_DELAY = 1 # 重试间隔时间,单位:秒 def promote(): # 模拟Promote方法 # 这里可以替换为实际的调用逻辑 return None # 模拟返回无效值 def call_promote_with_retry(): retries = 0 while retries < MAX_RETRIES: result = promote() if result is not None: return result retries += 1 time.sleep(RETRY_DELAY) return None final_result = call_promote_with_retry() if final_result is None: print("经过多次重试后,Promote方法仍然返回无效值") else: print("Promote方法返回有效结果:", final_result) ``` 对于数据库故障,要确保数据库的高可用性,可采用主从复制、集群等技术。同时,添加数据库操作的错误处理代码,例如: ```python import psycopg2 def promote_with_db_check(): try: # 连接数据库 conn = psycopg2.connect( database="your_database", user="your_user", password="your_password", host="your_host", port="your_port" ) cursor = conn.cursor() # 执行相关数据库操作 # ... result = promote() conn.commit() cursor.close() conn.close() return result except psycopg2.Error as e: print("数据库操作出现错误:", e) return None ``` 对于代码逻辑错误,需要仔细审查Promote方法的代码,进行单元测试和调试,确保逻辑的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值