1. 程式人生 > >資料庫多表操作事務處理

資料庫多表操作事務處理

一、主要思路

在需要同時插入多條資料時,這其中可能是同一個表的多條記錄,也可能是多個不同表之間的資料同時更新。對此,我們需要保證其中的原子性和一致性,做到要麼全部操作都能全部成功完成,否則全部不操作。

我們可以通過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