【问题标题】:Java DAO Insert Layer in Oracle Database [closed]Oracle 数据库中的 Java DAO 插入层 [关闭]
【发布时间】:2015-12-21 15:45:47
【问题描述】:

我有一个 DAO 层可以像这样插入 DERBY db,

try {
    long id = dbAccess.insert(connection,
        "INSERT INTO BOOKS(NAME, AUTHORS, PUBLISHYEAR, AVAIL) VALUES (?, ?, ?, ?)",
        new ScalarHandler<BigDecimal>(),
        book.getName(),
        book.getAuthors(),
        book.getPublishedYear(),
        book.isAvailable()
           ).longValue();
    return id;
} catch (Exception e) {
    e.printStackTrace();
}

return -1L;

如果我使用 ORACLE DB 作为数据源,我该如何翻译?

【问题讨论】:

  • 可能不同之处在于您设置连接的方式
  • 您在针对 Oracle 数据库尝试此操作时是否遇到了某种问题?

标签: java sql oracle dao


【解决方案1】:

我对您的数据库一无所知,但您需要定义插入表 id 的方法,并且您需要为您的 oracle 数据库创建连接类

您还需要管理表 id 增量,您应该创建一个触发器以在每次插入操作后递增表 id 我将发布一个从表中选择最大 id 的方法,您可以在下面的链接中找到 oracle 触发器来增加序列

How to create id with AUTO_INCREMENT on Oracle?

首先我们需要创建从你的表中返回最大 id 的方法

   public static int getMaxBookID(Connection connection){
   int id=0;
    String sql = "SELECT  NVL(MAX(ID),0)+1  FROM BOOK ";
    try{
    PreparedStatement statement = connection.prepareStatement(sql);
    if(statement!=null){
    try{
      ResultSet results = statement.executeQuery();
      if(results != null){
        try{
          if(results.next()){
            id = results.getInt(1);
          }
        }
        catch(Exception resultSetException) {resultSetException.printStackTrace();
        }
        results.close();
      }
    }
    catch(Exception statmentExcption){statmentExcption.printStackTrace();
    }
    statement.close();
  }
} catch (Exception generalException){generalException.printStackTrace();
}


return id;

}

这两种方法用于打开和关闭你的连接

  private static final String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";
  private static final String DB_CONNECTION = "jdbc:oracle:thin:@//host:1526/databasename";
private static final String DB_USER = "username";
private static final String DB_PASSWORD = "passowrd";

public static Connection lockConnection() {

    Connection dbConnection = null;

    try {

        Class.forName(DB_DRIVER);

    } catch (ClassNotFoundException e) {

        System.out.println(e.getMessage());

    }

    try {

        return DriverManager.getConnection(
                DB_CONNECTION, DB_USER, DB_PASSWORD);



    } catch (SQLException e) {

        System.out.println(e.getMessage());

    }

    return dbConnection;

}
public static void closeMyConnection(Connection connection) {

    try {

        connection.close();


    } catch (Exception ex) {
        ex.printStackTrace();
    }

}

现在您可以将您的信息插入到您的表格中

public int AddBook(String name,String auth,String year , String avail){
int id=0;

 Connection connection = lockConnection();
boolean ok = false;
String sql = "INSERT INTO BOOKS(ID,NAME, AUTHORS, PUBLISHYEAR, AVAIL)"


        + " VALUES(?,?,?,?,?)";


try{
  PreparedStatement statement = connection.prepareStatement(sql);
  if(statement!=null){
     statement.setInt(1,getMaxBookID(connection));
    statement.setString(2,name);
    statement.setString(3,auther);
    statement.setString(4,year);
    statement.setString(5,avail);




 try{
      int count = statement.executeUpdate();
      ok = count == 1;
      if(!ok)id=0;
    }
    catch(Exception statmentExcption){statmentExcption.printStackTrace();statmentExcption.printStackTrace(); return 0 ;
    }
    statement.close();
  }
} catch (Exception generalException){generalException.printStackTrace(); generalException.printStackTrace(); return 0;
}

closeMyConnection(connection);


return id;


}

【讨论】:

  • 该代码不返回新插入行的 ID,我认为这是问题的重点(无论如何我的解释)。
  • 我已经转发了我的答案,你可以再次查看
  • 如果两个线程并行执行此操作,它们将尝试添加相同的 ID。此外,它的效率不是很高。使用 SEQUENCE 对象来分配 ID 会更好,但会使 SQL 语句特定于 Oracle,除非您在触发器中执行此操作,但是您如何获取值?您使用可以返回生成值列的值的prepareStatement 版本。这样一来,您只需要一次访问数据库。
  • 那很好,我在我的帖子中使用了 prestatmnet,但是因为对您的表结构一无所知,所以建议您进行触发器以避免您的 ID 重复,有一个示例说明如何我从 oracle 数据库返回序列值,您只需在创建触发器和序列“SELECT YOURSEQName.NEXTVAL FROM DUAL”后更改我在 getNextBookId 中发布的选择查询,它将正常工作
【解决方案2】:

由于 Oracle 不支持 IDENTITY 列,您必须做两件事才能使其工作:

  • 创建一个 TRIGGER 以使用 SEQUENCE 分配 ID 值。
  • 按列名求值。

这意味着在构建PreparedStatement 时使用prepareStatement(String sql, String[] columnNames) 版本,而不是prepareStatement(String sql, int autoGeneratedKeys) 版本,因为Oracle 不知道哪个列是“自动生成的”。

使用名称版本适用于所有 DBMS 供应商,因此使用它会使您的代码供应商不可知:

  • Oracle:触发器
  • MySQL:AUTO_INCREMENT
  • MSSQL:IDENTITY
  • PostgreSQL:SERIAL
  • 德比:GENERATED ALWAYS AS IDENTITY
  • ...

【讨论】:

  • Oracle 12c does have support 用于标识列。
  • @MickMnemonic 啊,是的,忘记了。猜猜我的大脑卡在旧版本上。由于 OP 没有指定版本,我将把答案作为与版本无关的解决方案。
猜你喜欢
  • 2018-03-19
  • 1970-01-01
  • 1970-01-01
  • 2016-04-06
  • 2015-07-16
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多