/公共代碼:獲得數據庫鏈接 sql
public Connection getConnection() throws Exception{ 數據庫
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); 數組
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1 :1521:dbname", "username", "password"); 安全
return conn; 併發
} oracle
//方法一 性能
//先用select seq_t1.nextval as id from dual 取到新的sequence值。 spa
//而後將最新的值經過變量傳遞給插入的語句:insert into t1(id) values(?) .net
//最後返回開始取到的sequence值。 對象
//這種方法的優勢代碼簡單直觀,使用的人也最多,缺點是須要兩次sql交互,性能不佳。
public int insertDataReturnKeyByGetNextVal() throws Exception {
Connection conn = getConnection();
String vsql = "select seq_t1.nextval as id from dual";
PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql);
ResultSet rs=pstmt.executeQuery();
rs.next();
int id=rs.getInt(1);
rs.close();
pstmt.close();
vsql="insert into t1(id) values(?)";
pstmt =(PreparedStatement)conn.prepareStatement(vsql);
pstmt.setInt(1, id);
pstmt.executeUpdate();
System.out.print("id:"+id);
return id;
}
//方法二
//先用insert into t1(id) values(seq_t1.nextval)插入數據。
//而後使用select seq_t1.currval as id from dual返回剛纔插入的記錄生成的sequence值。
//注:seq_t1.currval表示取出當前會話的最後生成的sequence值,因爲是用會話隔離,只要保證兩個SQL使用同一個Connection便可,對於採用鏈接池應用須要將兩個SQL放在同一個事務內纔可保證併發安全。
//另外若是會話沒有生成過sequence值,使用seq_t1.currval語法會報錯。
//這種方法的優勢能夠在插入記錄後返回sequence,適合於數據插入業務邏輯很差改造的業務代碼,缺點是須要兩次sql交互,性能不佳,而且容易產生併發安全問題。
public int insertDataReturnKeyByGetCurrVal() throws Exception {
Connection conn = getConnection();
String vsql = "insert into t1(id) values(seq_t1.nextval)";
PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql);
pstmt.executeUpdate();
pstmt.close();
vsql="select seq_t1.currval as id from dual";
pstmt =(PreparedStatement)conn.prepareStatement(vsql);
ResultSet rs=pstmt.executeQuery();
rs.next();
int id=rs.getInt(1);
rs.close();
pstmt.close();
System.out.print("id:"+id);
return id;
}
//方法三
//採用pl/sql的returning into語法,能夠用CallableStatement對象設置registerOutParameter取得輸出變量的值。
//這種方法的優勢是隻要一次sql交互,性能較好,缺點是須要採用pl/sql語法,代碼不直觀,使用較少。
public int insertDataReturnKeyByPlsql() throws Exception {
Connection conn = getConnection();
String vsql = "begin insert into t1(id) values(seq_t1.nextval) returning id into :1;end;";
CallableStatement cstmt =(CallableStatement)conn.prepareCall ( vsql);
cstmt.registerOutParameter(1, Types.BIGINT);
cstmt.execute();
int id=cstmt.getInt(1);
System.out.print("id:"+id);
cstmt.close();
return id;
}
//方法四
//採用PreparedStatement的getGeneratedKeys方法
//conn.prepareStatement的第二個參數能夠設置GeneratedKeys的字段名列表,變量類型是一個字符串數組
//注:對Oracle數據庫這裏不能像其它數據庫那樣用prepareStatement(vsql,Statement.RETURN_GENERATED_KEYS)方法,這種語法是用來取自增類型的數據。
//Oracle沒有自增類型,所有采用的是sequence實現,若是傳Statement.RETURN_GENERATED_KEYS則返回的是新插入記錄的ROWID,並非咱們相要的sequence值。
//這種方法的優勢是性能良好,只要一次sql交互,實際上內部也是將sql轉換成oracle的returning into的語法,缺點是隻有Oracle10g才支持,使用較少。
public int insertDataReturnKeyByGeneratedKeys() throws Exception {
Connection conn = getConnection();
String vsql = "insert into t1(id) values(seq_t1.nextval)";
PreparedStatement pstmt =(PreparedStatement)conn.prepareStatement(vsql,new String[]{"ID"});
pstmt.executeUpdate();
ResultSet rs=pstmt.getGeneratedKeys();
rs.next();
int id=rs.getInt(1);
rs.close();
pstmt.close();
System.out.print("id:"+id);
return id;
}
//方法五
//和方法三相似,採用oracle特有的returning into語法,設置輸出參數,可是不一樣的地方是採用OraclePreparedStatement對象,由於jdbc規範裏標準的PreparedStatement對象是不能設置輸出類型參數。
//最後用getReturnResultSet取到新插入的sequence值,
//這種方法的優勢是性能最好,由於只要一次sql交互,oracle9i也支持,缺點是隻能使用Oracle jdbc特有的OraclePreparedStatement對象。
public int insertDataReturnKeyByReturnInto() throws Exception {
Connection conn = getConnection();
String vsql = "insert into t1(id) values(seq_t1.nextval) returning id into :1";
OraclePreparedStatement pstmt =(OraclePreparedStatement)conn.prepareStatement(vsql);
pstmt.registerReturnParameter(1, Types.BIGINT);
pstmt.executeUpdate();
ResultSet rs=pstmt.getReturnResultSet();
rs.next();
int id=rs.getInt(1);
rs.close();
pstmt.close();
System.out.print("id:"+id);
return id;
}
SQL> create table T1
2 (
3 ID NUMBER
4 );
Table created
SQL> create sequence SEQ_T1;
Sequence created