为 ID 列生成的键在表记录中返回 null

Posted

技术标签:

【中文标题】为 ID 列生成的键在表记录中返回 null【英文标题】:Generated keys for ID-column gives back null in table record 【发布时间】:2021-12-29 16:20:21 【问题描述】:

我是 Java 新手,尤其是 JDBC 新手。我正在尝试为 GUI 开发一个简单的 DAO 实现,其中面板中的字段被填写,数据存储在名为 EventList 的 Oracle DB 表中。目前,它适用于 Event (Model) 类的所有字段,EventID 列除外。

我正在尝试通过语句 GENERATED KEYS 生成一个自增整数,但是,即使我尝试了不同的方法来重新组织方法 saveData2() 中的“INSERT”查询,记录仍然为空并且没有生成任何键.我做错了什么?每一个提示都会非常感激!

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

public class EventDAOImpl implements EventDAO 

    @Override
    public void saveData2(Event event) 
        OracleDsSingleton ora =   OracleDsSingleton.getInstance();
        int primKey = 0;
        try 
            Connection connection = ora.getConnection();
            String addQuery = "INSERT INTO EventList(EventName, EventPlace, EventDate, EventDescription, EventCategory) VALUES (?,?,?,?,?)";
            //PreparedStatement ptmt = connection.prepareStatement(addQuery, Statement.RETURN_GENERATED_KEYS); 
//          ResultSet generatedKey = ptmt.getGeneratedKeys();
//                      if (generatedKey.next()) 
//              int key = generatedKey.getInt(1);
//              System.out.println(key);
//            
            String columnNames [] = new String [] "EventId";
            
            PreparedStatement ptmt = connection.prepareStatement(addQuery, columnNames);
            
            ptmt.setString(1, event.getName());
            ptmt.setString(2, event.getPlace());
            ptmt.setString(3, event.getDate());
            ptmt.setString(4, event.getDescription());
            ptmt.setString(5, event.getCategory());
            
            //ptmt.executeUpdate();
                        
            if(ptmt.executeUpdate() > 0) 
                java.sql.ResultSet generatedKey = ptmt.getGeneratedKeys();
                if (generatedKey.next() ) 
                    event.setEventID(generatedKey.getInt(1));
                
            
            System.out.println("Data successfully added!");
            //System.out.println("Table updated with EventID = " + primKey);
            System.out.println(event.getName());
            
            
         catch (SQLException e) 
            e.printStackTrace();
        
        
    

【问题讨论】:

请删除所有不需要演示问题的代码,尤其是与UI相关的代码,这些代码无关紧要。见How to ask。 请向我们展示 EventList 的创建表语句,特别是 EventId 是如何定义的(如果 DB 没有在插入时自动生成字段 - 没有什么可以返回) EventList 表是使用 SQL 查询直接在数据库中创建的。 EventID 被简单地定义为 Integer。 您使用的是哪个Oracle版本和哪个Oracle JDBC驱动版本? 【参考方案1】:

JDBC 标准中的大部分内容都是可选的。 DB 可以免费为 .getGeneratedKeys() 不返回任何内容。即使你要求他们。但你没有,所以,有希望!

首先尝试con.prepareStatement("SQL HERE", Statement.RETURN_GENERATED_KEYS)。但是,如果这不起作用,您将付出更多努力。运行查询以从序列中获取下一个值(并找出该序列的名称以执行此操作可能是一项艰巨的工作!),然后显式插入。让我们希望它不需要走到这一步。

注意:现代 DB 设计通常抛弃自动计数 ID 的概念,因为保持该计数器与复制的服务器“同步”以及所有这些爵士乐都是一个令人头疼的问题。如果您仍处于这一切的开始阶段,为什么不遵循现代惯例呢?将 ID 设为 UUID,然后让 java 生成它。它们不再是连续的值,相反,它们是长的随机生成的字符串(并且有足够的位,即使插入数万亿,如果插入仍然比您在被 2 个单独的流星撞击时不买彩票而中奖的机会更少,并且闪电,一下子)。

【讨论】:

以上是关于为 ID 列生成的键在表记录中返回 null的主要内容,如果未能解决你的问题,请参考以下文章

如何在sql中插入记录时返回id(id为自动增长)

仅当所有记录在特定列中都为 null 时,查询才返回 true

外部应用在不匹配时意外返回列NOT NULL

返回的键未设置 ID 字段

Golang pq sql驱动:批量导入后获取记录ID

根据主键在表上以正确的顺序插入行。