我正在运行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工程部门工作