資料庫多表操作事務處理
一、主要思路
在需要同時插入多條資料時,這其中可能是同一個表的多條記錄,也可能是多個不同表之間的資料同時更新。對此,我們需要保證其中的原子性和一致性,做到要麼全部操作都能全部成功完成,否則全部不操作。
我們可以通過SQL的事務來對相關資料庫操作進行處理,在開始conn.setAutoCommit(false);(conn是或得的連線)把本次執行的SQL操作改為非自動執行,在配置好各SQL語句之後,呼叫conn.commit();來執行,其中通過try{……}catch……來捕捉異常,如果遇到錯誤時,就呼叫conn.rollback();來對本次操作進行回滾到操作前的狀態,防止存在錯誤資料和髒資料。
二、主要實現方法
/** * 批量插入物件-同一個表多條記錄 * <p> * 注意:物件欄位不能為資料庫關鍵字 * @param list * @return * @throws SQLException * @author lims * @date 2015-08-28 */ public int[] insertSameTable(List<Pojo> list) throws SQLException { if (list == null || list.size() == 0) { return null; } String sql = getInsertSql(list.get(0)); PreparedStatement ps = null; String[] fields = null; int[] result = null; Connection conn=getConnection(); try { ps = conn.prepareStatement(sql.toString()); this.startTransaction(conn); for (Pojo obj : list) { Map<String, String> pojo_bean = obj.listInsertableFields(); fields = pojo_bean.keySet().toArray( new String[pojo_bean.size()]); for (int i = 0; i < fields.length; i++) { ps.setObject(i + 1, pojo_bean.get(fields[i])); } ps.addBatch(); } result = ps.executeBatch(); this.commitTransaction(conn); } catch(Exception e){ conn.rollback(); throw new RuntimeException(e); } finally { fields = null; org.apache.commons.dbutils.DbUtils.closeQuietly(ps); this.closeConnection(conn); } return result; } /** * 批量插入物件-多表插入 * <p> * 注意:物件欄位不能為資料庫關鍵字 * @param list * @return * @throws SQLException * @author lims * @date 2015-08-28 */ public int insertMutilTable(List<Pojo> list) throws SQLException { if (list == null || list.size() == 0) { return 0; } String[] fields; PreparedStatement ps = null; int result = 0; Connection conn=getConnection(); try { this.startTransaction(conn); for (Pojo obj : list) { Map<String, String> pojo_bean = obj.listInsertableFields(); String sql = getInsertSql(obj); ps = conn.prepareStatement(sql.toString()); fields = pojo_bean.keySet().toArray( new String[pojo_bean.size()]); for (int i = 0; i < fields.length; i++) { ps.setObject(i + 1, pojo_bean.get(fields[i])); } result = ps.executeUpdate(); } this.commitTransaction(conn); } catch(Exception e){ conn.rollback(); throw new RuntimeException(e); } finally { fields = null; org.apache.commons.dbutils.DbUtils.closeQuietly(ps); this.closeConnection(conn); } return result; } /** * 批量更新同一個表的多條記錄 * @param list * @return * @throws SQLException * @author lims * @date 2015-08-28 */ public int[] updateSameTable(List<Pojo> list) throws SQLException { if (list == null || list.size() == 0) { return null; } String[] fields; PreparedStatement ps = null; int[] result = null; Connection conn=getConnection(); try { this.startTransaction(conn); for (Pojo obj : list) { Map<String, String> pojo_bean = obj.listInsertableFields(); fields = pojo_bean.keySet().toArray( new String[pojo_bean.size()]); StringBuilder sql = new StringBuilder(); sql.append("update "+getTableName(obj.getClass())+" set "); for (int i = 0; i < fields.length; i++) { if (i > 0) sql.append(','); sql.append(fields[i]).append(" = ? "); } sql.append(" where id=?"); ps = conn.prepareStatement(sql.toString()); fields = pojo_bean.keySet().toArray( new String[pojo_bean.size()+1]); for (int i = 0; i < fields.length; i++) { if(i==fields.length-1) { ps.setObject(i + 1, obj.getId()); } else { ps.setObject(i + 1, pojo_bean.get(fields[i])); } } ps.addBatch(); } result = ps.executeBatch(); this.commitTransaction(conn); } catch(Exception e){ conn.rollback(); throw new RuntimeException(e); } finally { ps.clearBatch(); fields = null; org.apache.commons.dbutils.DbUtils.closeQuietly(ps); this.closeConnection(conn); } return result; } /** * 多表更新 * @param list * @return * @throws SQLException * @author lims * @date 2015-08-28 */ public int updateMutilTable(List<Pojo> list) throws SQLException { if (list == null || list.size() == 0) { return 0; } String[] fields; PreparedStatement ps = null; int result = 0; Connection conn=getConnection(); try { this.startTransaction(conn); for (Pojo obj : list) { Map<String, String> pojo_bean = obj.listInsertableFields(); String sql = getUpdateSql(obj); ps = conn.prepareStatement(sql.toString()); fields = pojo_bean.keySet().toArray( new String[pojo_bean.size()+1]); for (int i = 0; i < fields.length; i++) { if(i==fields.length-1) { ps.setObject(i + 1, obj.getId()); } else { ps.setObject(i + 1, pojo_bean.get(fields[i])); } } result = ps.executeUpdate(); } this.commitTransaction(conn); } catch(Exception e){ conn.rollback(); throw new RuntimeException(e); } finally { fields = null; org.apache.commons.dbutils.DbUtils.closeQuietly(ps); this.closeConnection(conn); } return result; } /** * 插入資料和更新多表資料 * @param list * @return * @throws SQLException * @author lims * @date 2015-08-28 */ public int insertAndUpdateMutilTable(List<Pojo> saveList,List<Pojo> updateList) throws SQLException { if (saveList == null || saveList.size() == 0 || updateList == null || updateList.size() == 0) { return 0; } String[] fields; PreparedStatement ps = null; int result = 0; Connection conn=getConnection(); try { this.startTransaction(conn); for (Pojo obj : saveList) {//插入操作 Map<String, String> pojo_bean = obj.listInsertableFields(); String sql = getInsertSql(obj); ps = conn.prepareStatement(sql.toString()); fields = pojo_bean.keySet().toArray( new String[pojo_bean.size()]); for (int i = 0; i < fields.length; i++) { ps.setObject(i + 1, pojo_bean.get(fields[i])); } result = ps.executeUpdate(); } for (Pojo obj : updateList) {//更新操作 Map<String, String> pojo_bean = obj.listInsertableFields(); String sql = getUpdateSql(obj); ps = conn.prepareStatement(sql.toString()); fields = pojo_bean.keySet().toArray( new String[pojo_bean.size()+1]); for (int i = 0; i < fields.length; i++) { if(i==fields.length-1) { ps.setObject(i + 1, obj.getId()); } else { ps.setObject(i + 1, pojo_bean.get(fields[i])); } } result = ps.executeUpdate(); } this.commitTransaction(conn); } catch(Exception e){ conn.rollback(); throw new RuntimeException(e); } finally { fields = null; org.apache.commons.dbutils.DbUtils.closeQuietly(ps); this.closeConnection(conn); } return result; }
三、相關呼叫方法
protected abstract Connection getConnection() throws SQLException; protected abstract void closeConnection(Connection conn); private void startTransaction(Connection conn) { try { if (conn != null) { conn.setAutoCommit(false); } } catch (Exception e) { throw new RuntimeException(e); } } private void commitTransaction(Connection conn) { try { if (conn != null) { conn.commit(); } } catch (Exception e) { throw new RuntimeException(e); } }
/**
* 獲取Pojo對應的資料庫表名
*
* @param c
* @return
*/
private static <T extends Pojo> String getTableName(Class<T> c) {
try {
String tn = tableNameCache.get(c.getSimpleName());
if (tn == null) {
tn = c.newInstance().tableName();
tableNameCache.put(c.getSimpleName(), tn);
}
return tn;
} catch (Exception e) {
log.error("Get " + c.getSimpleName() + " name exception.");
return null;
}
}
/**
* 獲取Pojo的插入sql語句
*
* @param obj
* @return
*/
private static String getInsertSql(Pojo obj) {
try {
String insertSql = insertSqlCache.get(obj.getClass().getName());
if (insertSql == null) {
Map<String, String> pojo_bean = obj.listInsertableFields();
String[] fields = pojo_bean.keySet().toArray(
new String[pojo_bean.size()]);
StringBuilder sql = new StringBuilder("INSERT INTO ");
sql.append(obj.tableName());
sql.append('(');
for (int i = 0; i < fields.length; i++) {
if (i > 0)
sql.append(',');
sql.append(fields[i]);
}
sql.append(") VALUES(");
for (int i = 0; i < fields.length; i++) {
if (i > 0)
sql.append(',');
sql.append('?');
}
sql.append(')');
insertSql = sql.toString();
sql = null;
insertSqlCache.put(obj.getClass().getName(), insertSql);
}
return insertSql;
} catch (Exception e) {
log.error("Get " + obj.getClass().getSimpleName()
+ " insertSql exception.");
return null;
}
}
/**
* 獲取Pojo的更新sql語句
*
* @param obj
* @return
* @author lims
* @date 2015-08-23
*/
private static String getUpdateSql(Pojo obj) {
try {
String updateSql = updateSqlCache.get(obj.getClass().getName());
if (updateSql == null) {
Map<String, String> pojo_bean = obj.listInsertableFields();
String[] fields = pojo_bean.keySet().toArray(
new String[pojo_bean.size()]);
StringBuilder sql = new StringBuilder();
sql.append("update "+getTableName(obj.getClass())+" set ");
for (int i = 0; i < fields.length; i++) {
if (i > 0)
sql.append(',');
sql.append(fields[i]).append(" = ? ");
}
sql.append(" where id=?");
updateSql = sql.toString();
sql = null;
updateSqlCache.put(obj.getClass().getName(), updateSql);
}
return updateSql;
} catch (Exception e) {
log.error("Get " + obj.getClass().getSimpleName()
+ " updateSql exception.");
return null;
}
}
四、上面用到的持久化基類
import org.apache.commons.beanutils.BeanUtils;
import java.io.Serializable;
import java.util.Map;
/**
* 持久化基類
*/
public abstract class Pojo implements Serializable {
private static final long serialVersionUID = 1L;
protected int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String tableName() {
String tn=getClass().getSimpleName() ;
if(tn.endsWith("Bean")) {
tn=tn.substring(0,tn.length()-4);
}
tn = tn.toLowerCase();
return tn;
}
protected String cacheRegion() {
return this.getClass().getSimpleName();
}
/**
* 列出要插入到資料庫的欄位集合,子類可以按照實際需求覆蓋
* @return
*/
public Map<String, String> listInsertableFields() {
try {
Map<String, String> props = BeanUtils.describe(this);
props.remove("id");
props.remove("class");
for(String s:props.keySet()){
if(s.endsWith("_"))props.remove(s);
}
return props;
} catch (Exception e) {
throw new RuntimeException("Exception when Fetching fields of "
+ this);
}
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
// 不同的子類儘管ID是相同也是不相等的
if (!getClass().equals(obj.getClass()))
return false;
Pojo wb = (Pojo) obj;
return wb.getId() == getId();
}
}
相關推薦
資料庫多表操作事務處理
一、主要思路 在需要同時插入多條資料時,這其中可能是同一個表的多條記錄,也可能是多個不同表之間的資料同時更新。對此,我們需要保證其中的原子性和一致性,做到要麼全部操作都能全部成功完成,否則全部不操作。 我們可以通過SQL的事務來對相關資料庫操作進行處理,在開始conn.se
資料庫分庫分表 sharding 系列 四 多資料來源的事務處理
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
java dbcp連接池,大數據處理循環多表操作插入事例
als postgresq postgres map() err manage fas space false 基礎連接池類: package com.yl.sys.dao; import java.io.InputStream;import java.sql.Connec
JDBC上關於資料庫中多表操作一對多關係和多對多關係的實現方法--轉
原文地址---- https://www.cnblogs.com/pangguoming/p/7028322.html 黑馬程式設計師 我們知道,在設計一個Java bean的時候,要把這些BEAN 的資料存放在資料庫中的表結構,然而這些資料庫中的表直接又有些特殊
Django - ORM 資料庫操作 - 多表操作
目錄 一、建立多表關係結構 二、一對多 and 一對一 表關係的記錄操作 1、 增(兩種方式) 方式一、create方式建立,指定欄位名傳輸資料 方式二、獲取外來鍵表物件id,給類定義的關係變數,賦值查詢到的物件 2、改(兩種方式) 方式一、獲取物件,修改後save方法儲
資料庫基礎 四張圖理解資料庫之第三張 資料庫連線 JDBC 理解 多表操作(附帶相關資源)第三天
JDBC JDBC: 概述: Java Data Base Connectivity,Java資料庫連線 就是Java程式碼操作不同資料庫(DBMS)。 JDBC就是Java定義的用來操作不同資料庫的規範,本質就是一些介面和類。
【python資料處理】pandas多表操作
pandas多表操作 1.Inner Merge 合併dataframe pd.merge()將兩張dataframe合成一張 除了pandas的方法,each DataFrame都有自己的merge()方法 查詢 類似於SELECT WHERE res
(十二)Hibernate中的多表操作(1):單向多對一
art 保存 int gen round t對象 情況 映射文件 拋出異常 由“多”方可知“一”方的信息,比如多個員工使用同一棟公寓,員工可以知道公寓的信息,而公寓無法知道員工的信息。 案例一: pojo類 public class Department {
(十四)Hibernate中的多表操作(4):單向一對一
odin utf-8 lds () clas string 方式 rdb style 案例一: 註解方式實現一對一 UserBean.java package bean; import java.io.Serializable; import javax.pers
【JAVAEE學習筆記】hibernate03:多表操作,級聯練習:添加聯系人
row tac 默認值 rac user except pro intra com 一、一對多|多對一 1、關系表達 表中的表達 實體中的表達 orm元數據中表達 一對多 <!-- 集合,一對多關系,在配置文件中配置 -
Hibernate筆記3--多表操作-導航查詢
test ransac mod 多表 private getc als 級聯 默認 一.一對多操作 1.構造實體類及編寫配置文件: 一方: 1 // 一個Customer對應多個linkman 2 private Set&l
MySQL之多表操作
cnblogs lec 外連接 自然連接 中軟 outer esc convert not in 前言:之前已經針對數據庫的單表查詢進行了詳細的介紹:MySQL之增刪改查,然而實際開發中業務邏輯較為復雜,需要對多張表進行操作,現在對多表操作進行介紹。 前提:為方便後面的操作
Hibernate的多表操作
nsa 執行 添加數據 什麽事 為什麽 -s 使用 一次 class 一.一對多 1.表設計:主外鍵關聯 2.持久類設計:一方持有多方的set集合,多方持有一方的對象 3.配置文件:一方配置級聯操作;一方放棄外鍵維護 二.多對多關系: 1
Django多表操作
輸入 ask __str__ models field pla 多對多 model class 多表操作:以book,publish, author為例 一對多:一旦確定一對多的關系,在多的一方(book)創建關聯字段publish_id 多對多:一旦確定多對多的
多表操作
pes class pytho 信息 會有 bsp day con ren 一、數據庫表關系 1、單表操作: Book id title price publish email addr 1 ph
Mysql-Sqlalchemy-多表操作
遊標 多表查詢 info mit span register mage kref first import sqlalchemy from sqlalchemy import create_engine from sqlalchemy.ext.declarative i
17-2 orm單表操作和多表操作
修改 rst and 默認 div tinc start 去掉 nta 參考:https://www.cnblogs.com/liwenzhou/p/8660826.html 一 ORM單表操作 1 增刪改查 1 1. 查詢 2 1. 查所有 3 models.P
django的多表操作
opened 例子 reat max ima bigint man all -m django的多表操作 1.使用場景 在實際生產過程多,我們面對的數據紛繁復雜,此時就需要良好的數據結構設計,多表之間的約束關系為我們提供了數據管理以及查詢的便利。在MYsql中我們利用外
web框架開發-Django模型層(2)-多表操作
增加 關系模型 進行 true ... 匹配條件 西遊記 port 覆寫 很重要,都是精華多表關系模型一對一一旦確定表關系是一對一,在兩張表中的任意一張表中建立關聯字段+Unique一對多一旦確定表關系是一對多,創建關聯字段在多的表中多對多一旦確定表關系是多對多,創建第三章
Django ORM 多表操作
ins print 一個 npr auto 到你 聯系 asc pos 創建模型 實例:我們來假定下面這些概念,字段和關系 作者模型:一個作者有姓名和年齡。 作者詳細模型:把作者的詳情放到詳情表,包含生日,手機號,家庭住址等信息。作者詳情模型和作者模型之間是一對一的關系(o