बैच INSERTs को संभालते समय यह पहला दृष्टिकोण JDBC ड्राइवर के व्यवहार के बारे में कोई धारणा नहीं बनाता है। यह
. द्वारा संभावित INSERT त्रुटियों से बचा जाता है- किसी भी मौजूदा
mail_id
के लिए तालिका से पूछताछ करना हमारे वर्तमान डेटा सेट में मान, - संबंधित
id
को नोट करता है उनmail_id
. के लिए मान मान जो मौजूद हैं, mail_id
को INSERT करता है वे मान जो मौजूद नहीं हैं, और उनके (नए)id
. को पुनः प्राप्त करते हैं मान, और फिर- पंक्तियों को दूसरी तालिका में सम्मिलित करता है (
inv_table
)।
try (Connection dbConn = DriverManager.getConnection(myConnectionString, "root", "usbw")) {
dbConn.setAutoCommit(false);
// test data and setup
Long aid = 123L;
List<MailidInvitation> invitationList = new ArrayList<MailidInvitation>();
invitationList.add(new MailidInvitation(13L));
invitationList.add(new MailidInvitation(11L));
invitationList.add(new MailidInvitation(12L));
// remove stuff from previous test run
try (Statement s = dbConn.createStatement()) {
s.executeUpdate("DELETE FROM mail_contacts WHERE mail_id IN (11,13)");
}
try (PreparedStatement ps = dbConn.prepareStatement(
"DELETE FROM inv_table WHERE aid=?")) {
ps.setLong(1, aid);
ps.executeUpdate();
}
// real code starts here
//
// create a Map to hold `mail_id` and their corresponding `id` values
Map<Long, Long> mailIdMap = new TreeMap<Long, Long>();
for (MailidInvitation a : invitationList) {
// mail_id, id (id is null for now)
mailIdMap.put(a.getId(), null);
}
// build an SQL statement to retrieve any existing values
StringBuilder sb = new StringBuilder(
"SELECT id, mail_id " +
"FROM mail_contacts " +
"WHERE mail_id IN (");
int n = 0;
for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
if (n++ > 0) sb.append(',');
sb.append(entry.getKey());
}
sb.append(')');
String sql = sb.toString();
// run the query and save the results (if any) to the Map
try (Statement s = dbConn.createStatement()) {
// <demo>
System.out.println(sql);
// </demo>
try (ResultSet rs = s.executeQuery(sql)) {
while (rs.next()) {
mailIdMap.put(rs.getLong("mail_id"), rs.getLong("id"));
}
}
}
// <demo>
System.out.println();
System.out.println("mailIdMap now contains:");
// </demo>
// build a list of the `mail_id` values to INSERT (where id == null)
// ... and print the existing mailIdMap values for demo purposes
List<Long> mailIdsToInsert = new ArrayList<Long>();
for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
String idValue = ""; // <demo />
if (entry.getValue() == null) {
mailIdsToInsert.add(entry.getKey());
// <demo>
idValue = "null";
} else {
idValue = entry.getValue().toString();
// </demo>
}
// <demo>
System.out.println(String.format(
" %d - %s",
entry.getKey(),
idValue));
// </demo>
}
// batch insert `mail_id` values that don't already exist
try (PreparedStatement ps = dbConn.prepareStatement(
"INSERT INTO mail_contacts (mail_id) VALUES (?)",
PreparedStatement.RETURN_GENERATED_KEYS)) {
for (Long mid : mailIdsToInsert) {
ps.setLong(1, mid);
ps.addBatch();
}
ps.executeBatch();
// get generated keys and insert them into the Map
try (ResultSet rs = ps.getGeneratedKeys()) {
n = 0;
while (rs.next()) {
mailIdMap.put(mailIdsToInsert.get(n++), rs.getLong(1));
}
}
}
// <demo>
System.out.println();
System.out.println("After INSERT INTO mail_contacts, mailIdMap now contains:");
for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
System.out.println(String.format(
" %d - %s",
entry.getKey(),
entry.getValue()));
}
// </demo>
// now insert the `inv_table` rows
try (PreparedStatement ps = dbConn.prepareStatement(
"INSERT INTO inv_table (mid, aid) VALUES (?,?)")) {
ps.setLong(2, aid);
for (MailidInvitation a : invitationList) {
ps.setLong(1, mailIdMap.get(a.getId()));
ps.addBatch();
}
ps.executeBatch();
}
dbConn.commit();
}
परिणामी कंसोल आउटपुट इस तरह दिखता है:
SELECT id, mail_id FROM mail_contacts WHERE mail_id IN (11,12,13)
mailIdMap now contains:
11 - null
12 - 1
13 - null
After INSERT INTO mail_contacts, mailIdMap now contains:
11 - 15
12 - 1
13 - 16
कुछ JDBC ड्राइवर बैच को जारी रखने की अनुमति देते हैं यदि बैच में एक या अधिक कथन विफल हो जाते हैं। उदाहरण के लिए, MySQL Connector/J में विकल्प है continueBatchOnError
जो true
है डिफ़ॉल्ट रूप से। उन मामलों में एक वैकल्पिक तरीका यह होगा कि सभी mail_id
. को आजमाएं और INSERT करें मान और बैच द्वारा लौटाए गए अद्यतनों की संख्या की जाँच करें। सफल INSERTs 1 की UpdateCount लौटाएंगे, जबकि INSERT जो मौजूदा mail_id
के कारण विफल हो जाते हैं EXECUTE_FAILED
लौटाएगा (-3)। तब हम (नया) id
. प्राप्त कर सकते थे .getGeneratedKeys()
. के माध्यम से सफल INSERTs के लिए मान , और फिर वापस जाने और id
. को पुनः प्राप्त करने के लिए एक SELECT स्टेटमेंट बनाने के लिए आगे बढ़ें mail_id
. के लिए मान प्रविष्टियाँ जो पहले से मौजूद थीं।
तो इस तरह कोड करें
// create a Map to hold `mail_id` and their corresponding `id` values
Map<Long, Long> mailIdMap = new TreeMap<Long, Long>();
for (MailidInvitation a : invitationList) {
// mail_id, id (id is null for now)
mailIdMap.put(a.getId(), null);
}
// try INSERTing all `mail_id` values
try (PreparedStatement ps = dbConn.prepareStatement(
"INSERT INTO mail_contacts (mail_id) VALUES (?)",
PreparedStatement.RETURN_GENERATED_KEYS)) {
for (Long mid : mailIdMap.keySet()) {
ps.setLong(1, mid);
ps.addBatch();
}
int[] updateCounts = null;
try {
updateCounts = ps.executeBatch();
} catch (BatchUpdateException bue) {
updateCounts = bue.getUpdateCounts();
}
// get generated keys and insert them into the Map
try (ResultSet rs = ps.getGeneratedKeys()) {
int i = 0;
for (Long mid : mailIdMap.keySet()) {
if (updateCounts[i++] == 1) {
rs.next();
mailIdMap.put(mid, rs.getLong(1));
}
}
}
}
// <demo>
System.out.println("mailIdMap now contains:");
// </demo>
// build a SELECT statement to get the `id` values for `mail_id`s that already existed
// ... and print the existing mailIdMap values for demo purposes
StringBuilder sb = new StringBuilder(
"SELECT id, mail_id " +
"FROM mail_contacts " +
"WHERE mail_id IN (");
int n = 0;
for (Map.Entry<Long, Long> entry : mailIdMap.entrySet()) {
String idValue = ""; // <demo />
if (entry.getValue() == null) {
if (n++ > 0) sb.append(',');
sb.append(entry.getKey());
// <demo>
idValue = "null";
} else {
idValue = entry.getValue().toString();
// </demo>
}
// <demo>
System.out.println(String.format(
" %d - %s",
entry.getKey(),
idValue));
// </demo>
}
sb.append(')');
String sql = sb.toString();
// <demo>
System.out.println();
System.out.println(sql);
// </demo>
इस तरह कंसोल आउटपुट उत्पन्न करेगा:
mailIdMap now contains:
11 - 17
12 - null
13 - 19
SELECT id, mail_id FROM mail_contacts WHERE mail_id IN (12)
बाकी प्रक्रिया पहले जैसी ही रहेगी:
- शेष
mailIdMap
भरें प्रविष्टियां, और - INSERTs को
id
. का उपयोग करके दूसरी टेबल पर प्रोसेस करेंmailIdMap
में मान ।