জেডিবিসিতে কীভাবে সন্নিবেশ আইডি পাবেন?


385

আমি INSERTজাভাতে জেডিবিসি ব্যবহার করে একটি ডাটাবেসে (যা আমার ক্ষেত্রে মাইক্রোসফ্ট এসকিউএল সার্ভার) রেকর্ড করতে চাই । একই সাথে, আমি sertোকানো আইডি পেতে চাই। আমি কীভাবে জেডিবিসি এপিআই ব্যবহার করে এটি অর্জন করতে পারি?


কোয়েরি getGeneratedKeys () এ অটোজেনারেটেড আইডিটি ছেড়ে দিন String sql = "INSERT INTO 'yash'.'mytable' ('name') VALUES (?)"; int primkey = 0 ; PreparedStatement pstmt = con.prepareStatement(sql, new String[] { "id" }/*Statement.RETURN_GENERATED_KEYS*/); pstmt.setString(1, name); if (pstmt.executeUpdate() > 0) { java.sql.ResultSet generatedKeys = pstmt.; if (generatedKeys.next()) primkey = generatedKeys.getInt(1); }
যশ

উত্তর:


650

যদি এটি একটি স্বয়ংক্রিয় উত্পন্ন কী হয় তবে আপনি এটির জন্য ব্যবহার করতে পারেন Statement#getGeneratedKeys()। আপনার এটির জন্য Statementযেমনটি ব্যবহার করা হচ্ছে ঠিক তেমন কল করতে হবে INSERT। আপনিই প্রথম প্রয়োজন স্টেটমেন্ট ব্যবহার তৈরি করতে Statement.RETURN_GENERATED_KEYSJDBC ড্রাইভার অবহিত করার কী দেখাবে।

এখানে একটি প্রাথমিক উদাহরণ:

public void create(User user) throws SQLException {
    try (
        Connection connection = dataSource.getConnection();
        PreparedStatement statement = connection.prepareStatement(SQL_INSERT,
                                      Statement.RETURN_GENERATED_KEYS);
    ) {
        statement.setString(1, user.getName());
        statement.setString(2, user.getPassword());
        statement.setString(3, user.getEmail());
        // ...

        int affectedRows = statement.executeUpdate();

        if (affectedRows == 0) {
            throw new SQLException("Creating user failed, no rows affected.");
        }

        try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
            if (generatedKeys.next()) {
                user.setId(generatedKeys.getLong(1));
            }
            else {
                throw new SQLException("Creating user failed, no ID obtained.");
            }
        }
    }
}

মনে রাখবেন যে আপনি জেডিবিসি ড্রাইভারের উপর নির্ভরশীল যে এটি কাজ করে কিনা। বর্তমানে, সর্বশেষ সংস্করণগুলির বেশিরভাগই কাজ করবে, তবে আমি যদি সঠিক হয়ে থাকি তবে ওরাকল জেডিবিসি ড্রাইভার এখনও এটিকে কিছুটা ঝামেলা করে। মাইএসকিউএল এবং ডিবি 2 ইতিমধ্যে যুগ যুগ ধরে এটি সমর্থন করেছে। পোস্টগ্র্রেএসকিউএল খুব বেশি দিন আগে এটি সমর্থন করা শুরু করে। আমি এমএসএসকিউএল সম্পর্কে মন্তব্য করতে পারি না কারণ আমি এটি কখনও ব্যবহার করি নি।

ওরাকল-এর জন্য, আপনি সর্বশেষ উত্পন্ন কীটি পাওয়ার জন্য একই লেনদেনের পরে সরাসরি CallableStatementএকটি RETURNINGধারা বা একটি SELECT CURRVAL(sequencename)(বা এটির জন্য ডিবি-নির্দিষ্ট সিনট্যাক্স) দিয়ে একটি আবেদন করতে পারেন INSERT। আরও দেখুন এই উত্তর


4
সন্নিবেশের পরে কার্কুল পাওয়ার চেয়ে সন্নিবেশের পূর্বে সিক্যুয়ালে পরের মানটি পাওয়া ভাল, কারণ পরবর্তীকালে বহু-থ্রেডযুক্ত পরিবেশে (যেমন কোনও ওয়েব অ্যাপ্লিকেশন ধারক) ভুল মান ফিরে আসতে পারে। জেটিডিএস এমএসএসকিউএল ড্রাইভার getGenratedKeys সমর্থন করে।
জিবি

4
(স্পষ্ট করে দেওয়া উচিত যে আমি সাধারণত ওরাকল ব্যবহার করি, তাই জেডিবিসি ড্রাইভারের দক্ষতা সম্পর্কে সাধারণত খুব কম প্রত্যাশা থাকে)।
জিবি

7
বিবৃতিটি সেট না করার একটি আকর্ষণীয় পার্শ্ব-প্রতিক্রিয়া RE RETURN_GENERATED_KEYS বিকল্পটি হচ্ছে ত্রুটি বার্তা, যা সম্পূর্ণ অস্পষ্ট "কোনও ফলাফল পাওয়ার আগে বিবৃতি কার্যকর করতে হবে" "
ক্রিস উইন্টারস 16

7
generatedKeys.next()আয় trueযদি ডিবি একটি উত্পন্ন কী ফিরে আসেন। দেখুন, এটি একটি ResultSet। এটি কেবল close()নিখরচায় সম্পদের জন্য। অন্যথায় আপনার ডিবি দীর্ঘমেয়াদে তা শেষ হয়ে যাবে এবং আপনার অ্যাপ্লিকেশনটি ব্রেক হয়ে যাবে। আপনাকে কেবল কিছু ইউটিলিটি পদ্ধতি নিজেই লিখতে হবে যা সমাপ্তির কাজটি করে। আরও দেখুন এই এবং এই উত্তর।
বালাসসি

5
বেশিরভাগ ডাটাবেস / ড্রাইভারের সঠিক উত্তর ওরাকল এর জন্য এটি তবে কাজ করে না। ওরাকল-এর জন্য, এই পরিবর্তন করুন:
ড্যারেল টিগু

24
  1. জেনারেটেড কলাম তৈরি করুন

    String generatedColumns[] = { "ID" };
  2. এই জেনেটেড কলামটি আপনার বিবৃতিতে পাস করুন

    PreparedStatement stmtInsert = conn.prepareStatement(insertSQL, generatedColumns);
  3. ResultSetবিবৃতিতে জেনারেটেড কীগুলি আনার জন্য অবজেক্টটি ব্যবহার করুন

    ResultSet rs = stmtInsert.getGeneratedKeys();
    
    if (rs.next()) {
        long id = rs.getLong(1);
        System.out.println("Inserted ID -" + id); // display inserted record
    }

8

আমি একক থ্রেডেড জেডিবিসি-ভিত্তিক অ্যাপ্লিকেশন থেকে মাইক্রোসফ্ট এসকিউএল সার্ভার ২০০৮ আর 2-কে হিট করছি এবং রিটার্ন_জেনারেট এ-কেইওয়াইএস সম্পত্তি বা কোনও প্রস্তুতিমূলক স্ট্যাটমেন্ট ব্যবহার না করে শেষ আইডিটি পিছনে টানছি। এরকম কিছু দেখাচ্ছে:

private int insertQueryReturnInt(String SQLQy) {
    ResultSet generatedKeys = null;
    int generatedKey = -1;

    try {
        Statement statement = conn.createStatement();
        statement.execute(SQLQy);
    } catch (Exception e) {
        errorDescription = "Failed to insert SQL query: " + SQLQy + "( " + e.toString() + ")";
        return -1;
    }

    try {
        generatedKey = Integer.parseInt(readOneValue("SELECT @@IDENTITY"));
    } catch (Exception e) {
        errorDescription = "Failed to get ID of just-inserted SQL query: " + SQLQy + "( " + e.toString() + ")";
        return -1;
    }

    return generatedKey;
} 

এই ব্লগ পোস্টটি তিনটি প্রধান এসকিউএল সার্ভারকে "শেষ আইডি" বিকল্পগুলি সুন্দরভাবে বিচ্ছিন্ন করেছে: http://msjawahar.wordpress.com/2008/01/25/how-to-find-thelast- stateity-value-insert-in- the -sql-সার্ভার / - এখনও অন্য দুটি প্রয়োজন নেই।


4
অ্যাপ্লিকেশনটিতে একটি মাত্র থ্রেড রয়েছে এমন একটি রেসের শর্তটিকে অসম্ভব করে তোলে না: যদি দুটি ক্লায়েন্ট একটি সারি সন্নিবেশ করে এবং আপনার পদ্ধতির সাহায্যে আইডি পুনরুদ্ধার করে তবে এটি ব্যর্থ হতে পারে।
11684

েরগেরগ? আমি কেবল আনন্দিত যে আমি দরিদ্র সোড নই যাকে একাধিক থ্রেড দেওয়ার সময় আপনার কোডটি ডিবাগ করতে হবে!
mjaggard

6

ব্যবহারের সময় 'অসমর্থিত বৈশিষ্ট্য' ত্রুটির মুখোমুখি হওয়ার সময় এটি ব্যবহার Statement.RETURN_GENERATED_KEYSকরে দেখুন:

String[] returnId = { "BATCHID" };
String sql = "INSERT INTO BATCH (BATCHNAME) VALUES ('aaaaaaa')";
PreparedStatement statement = connection.prepareStatement(sql, returnId);
int affectedRows = statement.executeUpdate();

if (affectedRows == 0) {
    throw new SQLException("Creating user failed, no rows affected.");
}

try (ResultSet rs = statement.getGeneratedKeys()) {
    if (rs.next()) {
        System.out.println(rs.getInt(1));
    }
    rs.close();
}

কোথায় BATCHIDস্বয়ংক্রিয় উত্পন্ন আইডি।


আপনার অর্থBATCHID
মুলসবিথওয়ে

দুর্দান্ত উত্তর !!!
হাসিথা জয়ওয়ার্দনা

3

আমি এসকিউএল সার্ভার ২০০৮ ব্যবহার করছি তবে আমার বিকাশের সীমাবদ্ধতা রয়েছে: আমি এর জন্য নতুন ড্রাইভার ব্যবহার করতে পারি না, আমাকে "com.microsoft.jdbc.sqlserver.SQLServerDriver" ব্যবহার করতে হবে (আমি "com.mic Microsoft.sqlserver.jdbc ব্যবহার করতে পারি না) .SQLServerDriver ")।

এটা কেন সমাধান conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)একটি ছুড়ে ফেলে java.lang.AbstractMethodError আমার জন্য। এই পরিস্থিতিতে, একটি সম্ভাব্য সমাধান আমি খুঁজে পেয়েছি মাইক্রোসফ্ট দ্বারা প্রস্তাবিত পুরানো: জেডিবিসি ব্যবহার করে কিভাবে @@ পরিচয় মান পুনরুদ্ধার করতে হবে

import java.sql.*; 
import java.io.*; 

public class IdentitySample
{
    public static void main(String args[])
    {
        try
        {
            String URL = "jdbc:microsoft:sqlserver://yourServer:1433;databasename=pubs";
            String userName = "yourUser";
            String password = "yourPassword";

            System.out.println( "Trying to connect to: " + URL); 

            //Register JDBC Driver
            Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();

            //Connect to SQL Server
            Connection con = null;
            con = DriverManager.getConnection(URL,userName,password);
            System.out.println("Successfully connected to server"); 

            //Create statement and Execute using either a stored procecure or batch statement
            CallableStatement callstmt = null;

            callstmt = con.prepareCall("INSERT INTO myIdentTable (col2) VALUES (?);SELECT @@IDENTITY");
            callstmt.setString(1, "testInputBatch");
            System.out.println("Batch statement successfully executed"); 
            callstmt.execute();

            int iUpdCount = callstmt.getUpdateCount();
            boolean bMoreResults = true;
            ResultSet rs = null;
            int myIdentVal = -1; //to store the @@IDENTITY

            //While there are still more results or update counts
            //available, continue processing resultsets
            while (bMoreResults || iUpdCount!=-1)
            {           
                //NOTE: in order for output parameters to be available,
                //all resultsets must be processed

                rs = callstmt.getResultSet();                   

                //if rs is not null, we know we can get the results from the SELECT @@IDENTITY
                if (rs != null)
                {
                    rs.next();
                    myIdentVal = rs.getInt(1);
                }                   

                //Do something with the results here (not shown)

                //get the next resultset, if there is one
                //this call also implicitly closes the previously obtained ResultSet
                bMoreResults = callstmt.getMoreResults();
                iUpdCount = callstmt.getUpdateCount();
            }

            System.out.println( "@@IDENTITY is: " + myIdentVal);        

            //Close statement and connection 
            callstmt.close();
            con.close();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

        try
        {
            System.out.println("Press any key to quit...");
            System.in.read();
        }
        catch (Exception e)
        {
        }
    }
}

এই সমাধানটি আমার পক্ষে কাজ করেছিল!

আশা করি এটা কাজে লাগবে!


1

নতুন sertedোকানো আইডি পেতে আপনি নিম্নলিখিত জাভা কোডটি ব্যবহার করতে পারেন।

ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, quizid);
ps.setInt(2, userid);
ps.executeUpdate();

ResultSet rs = ps.getGeneratedKeys();
if (rs.next()) {
    lastInsertId = rs.getInt(1);
}

0

কোনও মন্তব্যের পরিবর্তে , আমি কেবল পোস্টটির উত্তর দিতে চাই।


ইন্টারফেস java.sql.PreparedStatement

  1. কলাম ইনডেক্সস «আপনি ক্রেডিডেক্সটেক্স এবং এসকিউএল স্টেটমেন্ট গ্রহণ করে এমন স্টিপমেন্ট ফাংশন ব্যবহার করতে পারেন। যেখানে কলাম ইনডেক্সগুলি স্থির পতাকাগুলিকে অনুমোদিত স্টেটমেন্ট REআর রিটার্ন_জেনের্যাটED_KEYS 1 বা বিবৃতি N NO_GENERATED_KEYS [2], এসকিউএল বিবৃতিতে এক বা একাধিক 'থাকতে পারে?' পরামিতি প্লেসমোল্ডারগুলিতে।

    বাক্য গঠন "

    Connection.prepareStatement(String sql, int autoGeneratedKeys)
    Connection.prepareStatement(String sql, int[] columnIndexes)

    উদাহরণ:

    PreparedStatement pstmt = 
        conn.prepareStatement( insertSQL, Statement.RETURN_GENERATED_KEYS );

  1. columnNames « তালিকা columnNames মত 'id', 'uniqueID', ...। লক্ষ্য সারণীতে স্বতঃ-উত্পন্ন কীগুলি রয়েছে যা ফেরত দেওয়া উচিত। এসকিউএল স্টেটমেন্টটি স্টেটমেন্ট না হলে ড্রাইভার এগুলি উপেক্ষা করবে INSERT

    বাক্য গঠন "

    Connection.prepareStatement(String sql, String[] columnNames)

    উদাহরণ:

    String columnNames[] = new String[] { "id" };
    PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames );

সম্পূর্ণ উদাহরণ:

public static void insertAutoIncrement_SQL(String UserName, String Language, String Message) {
    String DB_URL = "jdbc:mysql://localhost:3306/test", DB_User = "root", DB_Password = "";

    String insertSQL = "INSERT INTO `unicodeinfo`( `UserName`, `Language`, `Message`) VALUES (?,?,?)";
            //"INSERT INTO `unicodeinfo`(`id`, `UserName`, `Language`, `Message`) VALUES (?,?,?,?)";
    int primkey = 0 ;
    try {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        Connection conn = DriverManager.getConnection(DB_URL, DB_User, DB_Password);

        String columnNames[] = new String[] { "id" };

        PreparedStatement pstmt = conn.prepareStatement( insertSQL, columnNames );
        pstmt.setString(1, UserName );
        pstmt.setString(2, Language );
        pstmt.setString(3, Message );

        if (pstmt.executeUpdate() > 0) {
            // Retrieves any auto-generated keys created as a result of executing this Statement object
            java.sql.ResultSet generatedKeys = pstmt.getGeneratedKeys();
            if ( generatedKeys.next() ) {
                primkey = generatedKeys.getInt(1);
            }
        }
        System.out.println("Record updated with id = "+primkey);
    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | SQLException e) {
        e.printStackTrace();
    }
}

0

হাইবারনেটের নেটিভ্যু কিওয়ারি দিয়ে আপনাকে একক রেজাল্টের পরিবর্তে রেজাল্টলিস্টটি ফিরে আসতে হবে, কারণ হাইবারনেট একটি স্থানীয় কোয়েরি পরিবর্তন করে

INSERT INTO bla (a,b) VALUES (2,3) RETURNING id

মত

INSERT INTO bla (a,b) VALUES (2,3) RETURNING id LIMIT 1

যদি আপনি একটি একক ফলাফল পাওয়ার চেষ্টা করেন যা বেশিরভাগ ডাটাবেসগুলিকে (কমপক্ষে PostgreSQL) সিন্ট্যাক্স ত্রুটির কারণ হতে পারে। এরপরে, আপনি তালিকা থেকে ফলাফল ID আনতে পারেন (যার মধ্যে সাধারণত এক আইটেম থাকে)।


0

এটি সাধারণের Statementপাশাপাশি ব্যবহার করা সম্ভব (শুধু নয় PreparedStatement)

Statement statement = conn.createStatement();
int updateCount = statement.executeUpdate("insert into x...)", Statement.RETURN_GENERATED_KEYS);
try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
  if (generatedKeys.next()) {
    return generatedKeys.getLong(1);
  }
  else {
    throw new SQLException("Creating failed, no ID obtained.");
  }
}

0

আমার ক্ষেত্রে ->

ConnectionClass objConnectionClass=new ConnectionClass();
con=objConnectionClass.getDataBaseConnection();
pstmtGetAdd=con.prepareStatement(SQL_INSERT_ADDRESS_QUERY,Statement.RETURN_GENERATED_KEYS);
pstmtGetAdd.setString(1, objRegisterVO.getAddress());
pstmtGetAdd.setInt(2, Integer.parseInt(objRegisterVO.getCityId()));
int addId=pstmtGetAdd.executeUpdate();              
if(addId>0)
{
    ResultSet rsVal=pstmtGetAdd.getGeneratedKeys();
    rsVal.next();
    addId=rsVal.getInt(1);
}

তবুও আমি মনে করি এটি পাওয়ার জন্য এটি দীর্ঘতর পদ্ধতি। আমি মনে করি আরও সংকুচিত সমাধানও হবে।
TheSagya

0

যদি আপনি স্প্রিং জেডিবিসি ব্যবহার করে থাকেন তবে Springোকানো আইডি পেতে আপনি স্প্রিংয়ের জেনারেটেডকি হোল্ডার ক্লাসটি ব্যবহার করতে পারেন।

এই উত্তরটি দেখুন ... কীভাবে স্প্রিং Jdbctemplate.update ব্যবহার করে আইডি qোকানো যায় (স্ট্রিং এসকিউএল, আপত্তি ... আরগস)


-6
Connection cn = DriverManager.getConnection("Host","user","pass");
Statement st = cn.createStatement("Ur Requet Sql");
int ret  = st.execute();

মাফ করবেন, তবে এটা কী হওয়ার কথা?
মুলসবিথওয়ে

1. createStatementথেকে পদ্ধতিটি Connectionকোনও প্যারাম আশা করে না। ২. executeপদ্ধতিটি Statementকোয়েরি সহ একটি স্ট্রিং প্রত্যাশা করে। ৩. executeপদ্ধতিটি ফিরে আসে: trueযদি প্রথম ফলাফলটি কোনও ResultSetবস্তু হয়; falseযদি এটি একটি আপডেট গণনা হয় বা কোনও ফলাফল নেই। docs.oracle.com/javase/7/docs/api/java/sql/…
আতিলাকামুরকা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.