Java SpringJDBC和复合主键

Java SpringJDBC和复合主键,java,spring,jdbc,Java,Spring,Jdbc,SpringJDBC中是否有一种方法可以在插入行时返回复合主键。 此复合主键由来自不同序列的值组成 非常感谢您的帮助 问候 Damien以下是单键的基本概念。末尾的长id是关键。如果您有多个序列,我建议只使用两个单独的语句来获取每个生成的键 JdbcTemplate template = getJdbcTemplate(); KeyHolder keyHolder = new GeneratedKeyHolder(); template.update( new PreparedState

SpringJDBC中是否有一种方法可以在插入行时返回复合主键。 此复合主键由来自不同序列的值组成

非常感谢您的帮助

问候
Damien

以下是单键的基本概念。末尾的长id是关键。如果您有多个序列,我建议只使用两个单独的语句来获取每个生成的键

JdbcTemplate template = getJdbcTemplate();
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(
    new PreparedStatementCreator() {
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
            PreparedStatement ps = connection.prepareStatement(...);
            return ps;
        }
    },
    keyHolder);
long id = keyHolder.getKey().longValue();

您使用的是什么数据库服务器?MySQL只允许每个表有一个自动增量字段,我想这种情况经常会发生,但如果不知道您的设置,很难说。假设您的表中只有一个自动生成的字段,那么INSERT必须知道进入第二个PK字段的值。Robert的代码应该用于检索生成的键值,最干净的解决方案可能是使用此生成的键值和您已经掌握的值在事后执行选择。

我认为您需要的是。代码看起来像,除非你必须打电话

keyHolder.getKeys()
而不是

keyHolder.getKey()
下面是一个完整的示例(在PostgreSQL 8.4上测试):

我的桌子:

CREATE TABLE test
(
  id serial NOT NULL,
  otherid serial NOT NULL,
  val text,
  CONSTRAINT test_pkey PRIMARY KEY (id, otherid)
)
这是您取回钥匙的方式:

public void doStuff() {
    KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(
            new PreparedStatementCreator() {
                public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                    PreparedStatement ps = connection.prepareStatement("insert into test(val) values (?)", Statement.RETURN_GENERATED_KEYS);
                    ps.setInt(1, 42);
                    return ps;
                }
            },
            keyHolder);

    keyHolder.getKeys().get("id");
    keyHolder.getKeys().get("otherid");
}
现在,如果您想直接从keyHolder获取复合键作为某个类的实例,这并不简单

JdbcTemplate使用ColumnMapRowMapper映射生成的键(生成的键作为结果集返回,至少在PostgreSQL上是这样。它实际上返回整行,就像在刚刚插入的行上执行select一样)。JdbcTemplate中的许多其他位置都使用了相同的ColumnMapRowMapper

这里唯一可能的扩展点是钥匙夹本身。以下是您可以做的:

public void doStuff() {
    CompositeKeyHolder keyHolder = new CompositeKeyHolder();
    ... same code here ...

    keyHolder.getCompositeKey();
}


class CompositeKeyHolder extends GeneratedKeyHolder {
    private boolean converted;

    public CompositeKey getCompositeKey() {
        return new CompositeKey((Integer)this.getKeys().get("id"), (Integer)this.getKeys().get("otherid"));
    }
}


class CompositeKey {

    private Integer id;

    private Integer otherId;

    CompositeKey(Integer id, Integer otherId) {
        this.id = id;
        this.otherId = otherId;
    }

    public Integer getId() {
        return id;
    }

    public Integer getOtherId() {
        return otherId;
    }

}

我想澄清一下“SpringJDBC”;你是指Hibernate映射还是其他JPA框架?我不知道Spring提供了任何内置JDBC功能。另一个注意事项:当表的记录由复合键唯一标识时,通常最好使用一个生成的主键列。特别是当复合键只是多个生成的列时。我会回顾一下你的数据库设计,看看简化这些东西是否会使使用这些框架变得更容易。单键是最简单的情况,不需要解释。复合键是个问题,似乎没有简单/有效的解决方案。这是真的,但我不确定Damien是否知道简单的答案。另一方面,如果在一条语句中使用两个生成的键将数据插入表中,这听起来像是一个潜在的设计缺陷。MySQL并不是其他数据库的良好指南——它是粗糙和原始的。适当的数据库很好地支持复合键,但是SpringJDBC似乎对这个概念没有很好的支持。