事务的四种特性

一 什么是事务
数据库事务是指作为单个逻辑工作单元执行的一系列操作(SQL语句)。这些操作要么全部执行,要么全部不执行。
为什么需要事务
经典的银行转账行为,A账户转给B账户10元,数据库操作需要两步,第一步A账户减10元,第二步B账户加10元,如果没有事务并且在两步中间发生异常,就会导致A的账户少了10元,但B的账户没有变化,如果不能保证这两步操作统一,银行的转账业务也没法进行展开了。
事务管理是每个数据库(oracle、mysql、db等)都必须实现的。
二 事务的四大特性
原子性 (atomicity):强调事务的不可分割.
一致性 (consistency):事务的执行的前后数据的完整性保持一致.
隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
持久性(durability) :事务一旦结束,数据就持久到数据库
事务运行模式(3种)

自动提交事务:默认事务管理模式。如果一个语句成功地完成,则提交该语句;如果遇到错误,则回滚该语句。
显式事务:以BEGIN TRANSACTION显式开始,以COMMIT或ROLLBACK显式结束。
隐性事务:当连接以此模式进行操作时,sql将在提交或回滚当前事务后自动启动新事务。无须描述事务的开始,只需提交或回滚每个事务。它生成连续的事务链。
下面做一个事务的示例:
JDBC用了Druid连接池
1、maven引包

<!--mysql驱动包 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.47</version>
	</dependency>
	<!--druid连接池 -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>1.1.10</version>
	</dependency>

1
2
3
4
5
6
7
8
9
10
11
12
2、数据库设计

CREATE TABLE account (
userid varchar(64) NOT NULL,
username varchar(64) NOT NULL,
accountbalance decimal(10,2) NOT NULL DEFAULT ‘0.00’,
createtime datetime DEFAULT NULL,
updatetime datetime DEFAULT NULL,
PRIMARY KEY (userid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO account VALUES (‘1001’, ‘张三’, ‘1000.00’, ‘2018-11-09 09:39:52’, ‘2018-11-09 09:39:55’);

INSERT INTO account VALUES (‘1002’, ‘李四’, ‘1000.00’, ‘2018-11-09 09:40:12’, ‘2018-11-09 09:40:14’);

在这里插入图片描述
3、建立jdbc.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/zhd?useUnicode=true&characterEncoding=UTF-8&InnoDB=true&useSSL=false
username=root
password=123456
1
2
3
4
4、建立连接池工具类DBPoolConnection

import java.io.InputStream;
import java.sql.SQLException;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.pool.DruidPooledConnection;

public class DBPoolConnection {
static Logger log = LoggerFactory.getLogger(DBPoolConnection.class);
private static DBPoolConnection dbPoolConnection = null;
private static DruidDataSource druidDataSource = null;

static {
	Properties properties = loadPropertiesFile("jdbc.properties");
	try {
		druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties); // DruidDataSrouce工厂模式
	} catch (Exception e) {
		log.error("获取配置失败");
	}
}

/**
 * @param string 配置文件名
 * @return Properties对象
 */
private static Properties loadPropertiesFile(String fullFile) {
	if (null == fullFile || fullFile.equals("")) {
		throw new IllegalArgumentException("Properties file path can not be null" + fullFile);
	}
	InputStream inputStream = null;
	Properties p = null;
	try {
		ClassLoader cl = DBPoolConnection.class.getClassLoader();
		inputStream = cl.getResourceAsStream(fullFile);
		p = new Properties();
		p.load(inputStream);
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		try {
			if (null != inputStream) {
				inputStream.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	return p;
}

/**
 * 数据库连接池单例
 * 
 * @return
 */
public static synchronized DBPoolConnection getInstance() {
	if (null == dbPoolConnection) {
		dbPoolConnection = new DBPoolConnection();
	}
	return dbPoolConnection;
}

/**
 * 返回druid数据库连接
 * 
 * @return
 * @throws SQLException
 */
public DruidPooledConnection getConnection() throws SQLException {
	return druidDataSource.getConnection();
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
5、建立JDBCUtil工具类

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**

  • 对jdbc的完整封装

*/
public class JDBCUtil {

public static Logger log = LoggerFactory.getLogger(JDBCUtil.class);

/**
 * insert update delete SQL语句的执行的统一方法
 * 
 * @param sql SQL语句
 * @param params 参数数组,若没有参数则为null
 * @return 受影响的行数
 */
public int executeUpdate(String sql, Object... params) {
	// 受影响的行数
	int affectedLine = 0;
	// 创建ResultSetMetaData对象
	Connection conn = null;
	PreparedStatement pst = null;
	try {
		// 获得连接
		conn = DBPoolConnection.getInstance().getConnection();
		// 调用SQL
		pst = conn.prepareStatement(sql);

		// 参数赋值
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				pst.setObject(i + 1, params[i]);
			}
		}
		/*
		 * 在此 PreparedStatement 对象中执行 SQL 语句, 该语句必须是一个 SQL 数据操作语言(Data
		 * Manipulation Language,DML)语句,比如 INSERT、UPDATE 或 DELETE
		 * 语句;或者是无返回内容的 SQL 语句,比如 DDL 语句。
		 */
		// 执行
		affectedLine = pst.executeUpdate();

	} catch (SQLException e) {
		System.out.println(e.getMessage());
	} finally {
		// 释放资源
		closeAll(conn, pst, null);
	}
	return affectedLine;
}

/**
 * insert update delete SQL语句的执行的统一方法
 * 
 * @param sql SQL语句
 * @param params 参数数组,若没有参数则为null
 * @return 受影响的行数
 */
public int executeUpdate(Connection conn, String sql, Object... params) {
	// 受影响的行数
	int affectedLine = 0;
	// 创建ResultSetMetaData对象
	PreparedStatement pst = null;
	try {
		// 获得连接
		// 调用SQL
		pst = conn.prepareStatement(sql);

		// 参数赋值
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				pst.setObject(i + 1, params[i]);
			}
		}
		/*
		 * 在此 PreparedStatement 对象中执行 SQL 语句, 该语句必须是一个 SQL 数据操作语言(Data
		 * Manipulation Language,DML)语句,比如 INSERT、UPDATE 或 DELETE
		 * 语句;或者是无返回内容的 SQL 语句,比如 DDL 语句。
		 */
		// 执行
		affectedLine = pst.executeUpdate();

	} catch (SQLException e) {
		System.out.println(e.getMessage());
	} finally {
		// 释放资源
		 close(pst);
	}
	return affectedLine;
}

/**
 * 获取结果集,并将结果放在List中
 * 
 * @param sql SQL语句 params 参数,没有则为null
 * @return List 结果集
 */
public List<Map<String, Object>> excuteQuery(String sql, Object... params) {
	// 创建ResultSetMetaData对象
	ResultSetMetaData rsmd = null;
	Connection conn = null;
	PreparedStatement pst = null;
	ResultSet rst = null;
	// 创建List
	List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
	try {
		conn = DBPoolConnection.getInstance().getConnection();
		// 调用SQL
		pst = conn.prepareStatement(sql);
		// 参数赋值
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				pst.setObject(i + 1, params[i]);
			}
		}
		// 执行
		rst = pst.executeQuery();
		rsmd = rst.getMetaData();
		// 获得结果集列数
		int columnCount = rsmd.getColumnCount();
		// 将ResultSet的结果保存到List中
		while (rst.next()) {
			Map<String, Object> map = new HashMap<String, Object>();
			for (int i = 1; i <= columnCount; i++) {
				map.put(rsmd.getColumnLabel(i), rst.getObject(i));
			}
			list.add(map);// 每一个map代表一条记录,把所有记录存在list中
		}

	} catch (SQLException e1) {
		System.out.println(e1.getMessage());
	} finally {
		// 关闭所有资源
		closeAll(conn, pst, rst);
	}
	return list;
}

/**
 * 关闭所有资源
 */
private void closeAll(Connection conn, PreparedStatement pst, ResultSet rst) {
	// 关闭结果集对象
	if (rst != null) {
		try {
			rst.close();
		} catch (SQLException e) {
			System.out.println(e.getMessage());
		}
	}

	// 关闭PreparedStatement对象
	if (pst != null) {
		try {
			pst.close();
		} catch (SQLException e) {
			System.out.println(e.getMessage());
		}
	}

	// 关闭Connection 对象
	if (conn != null) {
		try {
			conn.close();
		} catch (SQLException e) {
			System.out.println(e.getMessage());
		}
	}
}

/**
 * 关闭所有资源
 */
public void close(AutoCloseable autoCloseable) {
	if (autoCloseable != null) {
		try {
			autoCloseable.close();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}

/**
 * 通过反射机制查询单条记录
 * 
 * @param sql
 * @param params
 * @param cls
 * @return
 * @throws Exception
 */
public <T> T findSimpleRefResult(String sql, Class<T> cls, Object... params) {
	T resultObject = null;
	int index = 1;
	Connection conn = null;
	PreparedStatement pst = null;
	ResultSet rst = null;
	try {
		conn = DBPoolConnection.getInstance().getConnection();
		pst = conn.prepareStatement(sql);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				pst.setObject(index++, params[i]);
			}
		}
		rst = pst.executeQuery();
		ResultSetMetaData metaData = rst.getMetaData();
		int cols_len = metaData.getColumnCount();
		while (rst.next()) {
			// 通过反射机制创建一个实例
			resultObject = cls.newInstance();
			for (int i = 0; i < cols_len; i++) {
				String cols_name = metaData.getColumnName(i + 1);
				Object cols_value = rst.getObject(cols_name);
				if (cols_value == null) {
					cols_value = "";
				}
				try {
					Field field = cls.getDeclaredField(cols_name.toLowerCase());
					field.setAccessible(true); // 打开javabean的访问权限
					field.set(resultObject, cols_value);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		closeAll(conn, pst, rst);
	}
	return resultObject;

}

/**
 * 通过反射机制查询多条记录
 * 
 * @param sql
 * @param params
 * @param cls
 * @return
 * @throws Exception
 */
public <T> List<T> findMoreRefResult(String sql, Class<T> cls, Object... params) {
	List<T> list = new ArrayList<T>();
	int index = 1;
	Connection connection = null;
	PreparedStatement pstmt = null;
	ResultSet resultSet = null;
	try {
		connection = DBPoolConnection.getInstance().getConnection();
		pstmt = connection.prepareStatement(sql);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				pstmt.setObject(index++, params[i]);
			}
		}
		resultSet = pstmt.executeQuery();
		ResultSetMetaData metaData = resultSet.getMetaData();
		int cols_len = metaData.getColumnCount();
		while (resultSet.next()) {
			// 通过反射机制创建一个实例
			T resultObject = cls.newInstance();
			for (int i = 0; i < cols_len; i++) {
				String cols_name = metaData.getColumnName(i + 1);
				Object cols_value = resultSet.getObject(cols_name);
				if (cols_value == null) {
					cols_value = "";
				}
				try {
					Field field = cls.getDeclaredField(cols_name.toLowerCase());
					field.setAccessible(true); // 打开javabean的访问权限
					field.set(resultObject, cols_value);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			list.add(resultObject);
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		closeAll(connection, pstmt, resultSet);
	}
	return list;
}

/**
 * 通过反射机制查询多条记录
 * 
 * @param sql
 * @param params
 * @param cls
 * @return
 * @throws Exception
 */
public List<String> findMoreRefResult(String sql, Object... params) {
	List<String> list = new ArrayList<String>();
	int index = 1;
	Connection connection = null;
	PreparedStatement pstmt = null;
	ResultSet resultSet = null;
	try {
		connection = DBPoolConnection.getInstance().getConnection();
		pstmt = connection.prepareStatement(sql);
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				pstmt.setObject(index++, params[i]);
			}
		}
		resultSet = pstmt.executeQuery();
		while (resultSet.next()) {
			// 通过反射机制创建一个实例
			String cols_value = resultSet.getString(1);
			list.add(cols_value);
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		closeAll(connection, pstmt, resultSet);
	}
	return list;
}

/**
 * SQL 查询将查询结果:一行一列
 * 
 * @param sql SQL语句
 * @param params 参数数组,若没有参数则为null
 * @return 结果集
 */
public Object executeQuerySingle(String sql, Object... params) {
	Connection conn = null;
	PreparedStatement pst = null;
	ResultSet rst = null;
	Object object = null;
	try {
		// 获得连接
		conn = DBPoolConnection.getInstance().getConnection();
		// 调用SQL
		pst = conn.prepareStatement(sql);
		// 参数赋值
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				pst.setObject(i + 1, params[i]);
			}
		}
		// 执行
		rst = pst.executeQuery();
		if (rst.next()) {
			object = rst.getObject(1);
		}
	} catch (SQLException e) {
		e.printStackTrace();
	} finally {
		closeAll(conn, pst, rst);
	}

	return object;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
5、进行测试:

正常情况下:

public class JDBCTest {
public static void main(String[] args) {
JDBCUtil jdbcUtil = new JDBCUtil();
Connection conn = null;
try {
conn = DBPoolConnection.getInstance().getConnection();
conn.setAutoCommit(false);
String sql_1 = “update account set accountbalance = accountbalance + ? where userid = ?”;
String sql_2 = “update account set accountbalance = accountbalance - ? where userid = ?”;
int line_1 = jdbcUtil.executeUpdate(conn, sql_1, 10, “1001”);
int line_2 = jdbcUtil.executeUpdate(conn, sql_2, 10, “1002”);
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
jdbcUtil.close(conn);
}
}
}
在这里插入图片描述
在这里插入图片描述
异常情况下:

public class JDBCTest {
public static void main(String[] args) {
JDBCUtil jdbcUtil = new JDBCUtil();
Connection conn = null;
try {
conn = DBPoolConnection.getInstance().getConnection();
conn.setAutoCommit(false);
String sql_1 = “update account set accountbalance = accountbalance + ? where userid = ?”;
String sql_2 = “update account set accountbalance = accountbalance - ? where userid = ?”;
int line_1 = jdbcUtil.executeUpdate(conn, sql_1, 10, “1001”);
if (line_1 == 1) {
throw new RuntimeException();
}
int line_2 = jdbcUtil.executeUpdate(conn, sql_2, 10, “1002”);
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
jdbcUtil.close(conn);
}
}
}

在这里插入图片描述
在这里插入图片描述

展开阅读全文

Python数据分析与挖掘

01-08
92讲视频课+16大项目实战+源码+¥800元课程礼包+讲师社群1V1答疑+社群闭门分享会=99元   为什么学习数据分析?       人工智能、大数据时代有什么技能是可以运用在各种行业的?数据分析就是。       从海量数据中获得别人看不见的信息,创业者可以通过数据分析来优化产品,营销人员可以通过数据分析改进营销策略,产品经理可以通过数据分析洞察用户习惯,金融从业者可以通过数据分析规避投资风险,程序员可以通过数据分析进一步挖掘出数据价值,它和编程一样,本质上也是一个工具,通过数据来对现实事物进行分析和识别的能力。不管你从事什么行业,掌握了数据分析能力,往往在其岗位上更有竞争力。    本课程共包含五大模块: 一、先导篇: 通过分析数据分析师的一天,让学员了解全面了解成为一个数据分析师的所有必修功法,对数据分析师不在迷惑。   二、基础篇: 围绕Python基础语法介绍、数据预处理、数据可视化以及数据分析与挖掘......这些核心技能模块展开,帮助你快速而全面的掌握和了解成为一个数据分析师的所有必修功法。   三、数据采集篇: 通过网络爬虫实战解决数据分析的必经之路:数据从何来的问题,讲解常见的爬虫套路并利用三大实战帮助学员扎实数据采集能力,避免没有数据可分析的尴尬。   四、分析工具篇: 讲解数据分析避不开的科学计算库Numpy、数据分析工具Pandas及常见可视化工具Matplotlib。   五、算法篇: 算法是数据分析的精华,课程精选10大算法,包括分类、聚类、预测3大类型,每个算法都从原理和案例两个角度学习,让你不仅能用起来,了解原理,还能知道为什么这么做。
©️2020 CSDN 皮肤主题: 游动-白 设计师: 上身试试 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值