此数据库不支持getGeneratedKeys功能

时间:2015-04-29 16:07:46

标签: jdbc spring-jdbc sqlanywhere

我正在运行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位于Tomcat lib目录中)。来自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会为此工作,对,因为这只会延迟提交,直到所有语句都成功为止?

1 个答案:

答案 0 :(得分:0)

我根本不是JDBC专家所以我不能直接回答这个问题,但我可以告诉你SQL Anywhere服务器肯定有这种能力。如果JDBC内容不起作用,您可以使用@@identity变量。获取select @@identity将返回最后一个语句的自动生成值。

免责声明:我在SQL Anywhere工程中为SAP工作。