(原文出自:http://www.theserverside.com/news/thread.tss?thread_id=63243)
在Java应用中代理主键的生成策略会因数据库甚至JDBC驱动程序的不同而不同,针对某一数据库或JDBC驱动的相关文档已经有很多,一个很好的总结是在这儿,大致包括:
- 修改SQL语句以适合数据库
- 修改Java代码以适合数据库或驱动
- 使用Java代码产生主键
使用Hibernate会帮助做这个事,但对于不同的数据库还是需要不同的XML配置,而我倾向于尽可能不使用不同的映射文件,况且我还不是持久层框架的狂热粉丝,大部分情况还在自己写DAO。
我的目标是在Java层面实现一个适合所有数据库的统一模式,只需在数据库层进行不同配置。希望通过配置不同JDBC参数就可以在不同数据库之间切换。我查了一下Oracle、MySQL和SQL Server的情况,发现相关的文章和方案非常多,就是需要花很多时间。现在把他们总结在这一个地方。
共用的Java代码
这是每个数据库都通用的Java代码:
// assume you have created a connection con
Statement stmt = con.createStatement();
//defines the field value to return to your code after the insert takes place
String [] pk = {"id"};
stmt.executeUpdate("INSERT INTO test (name) VALUES ('test')",pk);
ResultSet rs = s.getGeneratedKeys();
if(rs.next()){
int id_val = rs.getInt(1);
System.out.println("Your generated ID passed back to use as you wish: " + id_val);
}
rs.close();
stmt.close();
MySQL:
使用 auto-increment 域来产生唯一键值,比较简单:
CREATE TABLE test(
id INTEGER auto_increment PRIMARY KEY,
description VARCHAR(20));
SQL Server:
使用 IDENTITY 列属性来产生唯一键值,也同样简单:
CREATE TABLE calendar (
id INTEGER IDENTITY(1, 1) PRIMARY KEY,
description VARCHAR(20)
);
Oracle:
Oracle比较特殊,没有自动生成键值的列属性。不过你可以借助序列(Sequence)生成键值,并通过触发器(Trigger)应用到插入(Insert)操作上来实现。适用于 JDBC driver 10.2 以上版本:
CREATE TABLE calendar (
id NUMBER PRIMARY KEY,
description VARCHAR(20)
);
CREATE SEQUENCE test_sequence
START WITH 1INCREMENT BY 1;
CREATE OR REPLACE TRIGGER test_trigger
BEFORE INSERT
ON test
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT test_sequence.nextval INTO :NEW.ID FROM dual;
END;
/
总结:
对每一种数据库都试一下上面的代码,再看看那些自动生成的列,呵呵。
这个不是火箭科技,也没有在其它文档中查不到的东西,只是在这里对多个数据库汇总并测试一下,想方便那些和我一样自己写持久层并且需要同时支持多个异种数据库的同学。
=======================================
agnostic key : 我的理解是无意义流水键,或者代理主键。实际上,可能surrogate这个词在业界的使用更为广泛。不常见的叫synthetic key,更直白,人工合成键,呵呵。