此数据库不支持getGeneratedKeys功能



我正在运行SQL Anywhere 16.0,并尝试使用Spring JDBC模板。我需要做的非常简单:在表中插入一行,然后返回自动生成的ID值。

public int log() {
SimpleJdbcInsert insertActor = 
new SimpleJdbcInsert(ds)
.withTableName("DBA.REQUESTS")
.usingGeneratedKeyColumns("REQUEST_ID");
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("USER_ID", userId);
parameters.put("DATA_TYPE_ID", getProductSku());
parameters.put("PRICE", price);
// ...more parameters
Number requestIdNumber = insertActor.executeAndReturnKey(parameters);
return requestIdNumber.intValue();
}

但Spring一再给我错误

org.springframework.dao.InvalidDataAccessResourceUsageException: 
The getGeneratedKeys feature is not supported by this database

我使用的驱动程序应该支持JDBC 4.0(库是dbjdbc16.dll,它在路径中,sajdbc4.jar在Tomcatlib目录中)。Tomcat的相关数据库连接信息为

<Resource auth="Container" description="Pooled connection to the web database" 
driverClassName="sybase.jdbc4.sqlanywhere.IDriver" 
maxActive="30" maxIdle="5" maxWait="10000" name="jdbc/web" 
removeAbandoned="true" 
removeAbandonedTimeout="60" 
type="javax.sql.DataSource" 
url="jdbc:sqlanywhere:Server=web;UID=xxx;PASSWORD=xxx;port=xxxx;LINKS=tcpip(PORT=xxxx)"/>

数据源的Spring应用程序上下文是

<jee:jndi-lookup id="dbDataSource" jndi-name="jdbc/web"
expected-type="javax.sql.DataSource" />  

所以我的问题是,有没有一种方法可以更好地配置,使这种类型的语句发挥作用?OR如果数据库在某些基本级别上确实不支持这一点,是否有一个非丑陋的替代方案可以让我插入值并返回生成的id。

更新:数据库驱动程序似乎不支持此功能。这里和其他地方的建议是立即执行INSERT而不是SELECT。当然,问题是,如果另一个用户在这两条语句之间插入到表中,你会得到错误的值,在这种情况下,这将非常糟糕。

我现在的解决方法是在相关的DAO上使用类级锁,并根据几个列(而不仅仅是IDENTITY)进行选择,这样我就可以99.9%地确定我会得到同一行。它足够好工作了。也就是说,我更喜欢使用事务性的方式来锁定表。我不认为标记函数@Transactional会起作用,对吧,因为这只会延迟提交,直到所有语句都成功?

我根本不是JDBC专家,所以我不能直接回答问题,但我可以告诉您,SQL Anywhere服务器确实具有此功能。如果JDBC的东西不起作用,可以使用@@identity变量。正在获取select @@identity,它将返回最后一条语句的自动生成值。

免责声明:我在SAP的SQL Anywhere工程部门工作

最新更新