我似乎无法获得正确的魔法组合来完成这项工作:
OracleDataSource ods = new oracle.jdbc.pool.OracleDataSource();
ods.setURL("jdbc:oracle:thin:app_user/pass@server:1521:sid");
DefaultContext conn = ods.getConnection();
CallableStatement st = conn.prepareCall("INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO :rowid0");
st.registerReturnParameter(1, OracleTypes.ROWID);
st.execute();
我得到的错误是“违反协议”。如果我更改为registerOutParameter(),我会收到通知我没有注册所有返回变量。如果我将语句包装在PL / SQL中开始;结束;然后我使用常规的registerOutParameter()调用得到参数。我真的更愿意避免在PL / SQL中包装所有的insert语句 - 那么上面缺少什么?
答案 0 :(得分:15)
通常您不希望依赖于代码数据库。您应该使用CallableStatement而不是OraclePreparedStatement。
CallableStatement statement = connection.prepareCall("{call INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO ? }");
statement.registerOutParameter( 1, Types.VARCHAR );
int updateCount = statement.executeUpdate();
if (updateCount > 0) {
return statement.getString(1);
}
答案 1 :(得分:6)
您需要做的一些事情
从查询中返回信息的示例代码:
OraclePreparedStatement pstmt = (OraclePreparedStatement)conn.prepareStatement(
"delete from tab1 where age < ? returning name into ?");
pstmt.setInt(1,18);
/** register returned parameter
* in this case the maximum size of name is 100 chars
*/
pstmt.registerReturnParameter(2, OracleTypes.VARCHAR, 100);
// process the DML returning statement
count = pstmt.executeUpdate();
if (count>0)
{
ResultSet rset = pstmt.getReturnResultSet(); //rest is not null and not empty
while(rset.next())
{
String name = rset.getString(1);
...
}
}
有关Oracle JDBC扩展的更多信息:
答案 2 :(得分:3)
不知道这是否适用,因为您没有指定您正在使用的版本。
来自Oracle Metalink:
<强>原因强>
在10.1.0.x JDBC驱动程序中,不支持返回DML:
根据JDBC FAQ: “10.1.0(10g r1) DML返回是否受支持? 不在当前的驱动程序中。但是,我们确实计划在10.1.0之后的驱动程序中支持它。我们 这次真的很有意思。“
由于应用程序代码试图使用不受支持的JDBC功能,因此会引发错误。
<强>解决方案强>
将JDBC驱动程序升级到10.2.0.x,因为根据FAQ,10.2.0.x JDBC驱动程序支持返回子句:
“10.2.0(10g r2) DML返回是否受支持? 是!这是关于时间的。有关详细信息,请参阅开发人员指南。 “
修改强> 只是为了笑容,您可以检查Oracle认为它正在使用的JDBC版本:
// Create Oracle DatabaseMetaData object
DatabaseMetaData meta = conn.getMetaData();
// gets driver info:
System.out.println("JDBC driver version is " + meta.getDriverVersion());
如果显示的是JDBC驱动程序10.2.0.x或更高版本,那么我就没有想法了,也许对oracle的支持请求是有序的......
答案 3 :(得分:1)
尝试在SQL字符串上使用?而不是:rowid0 。我之前遇到过命名参数和Oracle的问题。
答案 4 :(得分:1)
PreparedStatement prepareStatement = connection.prepareStatement("insert...",
new String[] { "your_primary_key_column_name" });
prepareStatement.executeUpdate();
ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
if (null != generatedKeys && generatedKeys.next()) {
Long primaryKey = generatedKeys.getLong(1);
}
我找到了答案,这完全有效。我可以从JAVA插入并使用密钥返回。
完整版:
CREATE TABLE STUDENTS
(
STUDENT_ID NUMBER NOT NULL PRIMARY KEY,
NAME VARCHAR2 (50 BYTE),
EMAIL VARCHAR2 (50 BYTE),
BIRTH_DATE DATE
);
CREATE SEQUENCE STUDENT_SEQ
START WITH 0
MAXVALUE 9999999999999999999999999999
MINVALUE 0;
和Java代码
String QUERY = "INSERT INTO students "+
" VALUES (student_seq.NEXTVAL,"+
" 'Harry', 'harry@hogwarts.edu', '31-July-1980')";
// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");
// get database connection from connection string
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:sample", "scott", "tiger");
// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
new String[] { "student_id" });
// local variable to hold auto generated student id
Long studentId = null;
// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {
// getGeneratedKeys() returns result set of keys that were auto
// generated
// in our case student_id column
ResultSet generatedKeys = ps.getGeneratedKeys();
// if resultset has data, get the primary key value
// of last inserted record
if (null != generatedKeys && generatedKeys.next()) {
// voila! we got student id which was generated from sequence
studentId = generatedKeys.getLong(1);
}
}
来源:http://viralpatel.net/blogs/oracle-java-jdbc-get-primary-key-insert-sql/