- 浏览: 1249688 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (193)
- ant/maven (6)
- algorithm (5)
- tomcat/weblogic/jboss (6)
- javascript/jquery (13)
- java (33)
- flex/flash (0)
- JPA/Hibernate/myBatis (18)
- java concurrent (7)
- test (2)
- windows/linux (6)
- java collection (7)
- design pattern (2)
- life/health (3)
- database (12)
- IDE (4)
- spring/ejb (20)
- html/css/ckeditor (7)
- jsp/servlet (3)
- java io (13)
- java security (4)
- jni (0)
- svn/git (2)
- english (2)
- java jmx (1)
- xml (1)
- struts/springmvc (9)
- middleware (2)
- cache (1)
- cglib (3)
最新评论
-
jlotusYo:
博主,真感谢。
Java 密码扩展无限制权限策略文件 -
senninha:
这个。。是api说明吧。。
ScheduledExecutorService 源码分析 -
zoutao2008:
请问大文件如何处理?按你这种方式的话,文件超过200M时就会报 ...
hessian系列之二:上传文件 -
lwj1113:
lwj1113 写道谢谢博主这么细致的demo;在系列五中通过 ...
myBatis系列之五:与Spring3集成 -
lwj1113:
谢谢博主这么细致的demo;在系列五中通过testng测试类跑 ...
myBatis系列之五:与Spring3集成
本地事务即对一个数据源进行操作。大多数数据库支持事务。
先看没有事务的时候,导致的数据不一致问题。
准备数据:
Maven依赖:
接口:
实现类:
Spring配置文件:
测试:
用户user1的余额是20,买了3个单价为10的苹果,余额不够支付,报错。但是数据处于不一致状态:fruit_stock表的苹果存量由10个减为7个,而账户表的余额还是20,需要使用事务。
使用JDBC的事务操作。
上面的数据源是写在代码里的,每次修改都需要重新编译,可以将其放在Spring配置中:
先看没有事务的时候,导致的数据不一致问题。
准备数据:
-- MySQL -- Create the database DROP DATABASE IF EXISTS spring; CREATE DATABASE spring -- Drop three tables if exist DROP TABLE IF EXISTS FRUIT; DROP TABLE IF EXISTS FRUIT_STOCK; DROP TABLE IF EXISTS ACCOUNT; -- 水果表 CREATE TABLE FRUIT ( ID INT NOT NULL, FRUIT_NAME VARCHAR(100) NOT NULL, PRICE INT, PRIMARY KEY (ID) ); -- 水果存货表 CREATE TABLE FRUIT_STOCK ( ID INT NOT NULL, STOCK INT NOT NULL, PRIMARY KEY (ID), CHECK (STOCK >= 0) -- analyzed but ignored by MySQL ); -- 账户表 CREATE TABLE ACCOUNT ( USERNAME VARCHAR(50) NOT NULL, BALANCE INT NOT NULL, PRIMARY KEY (USERNAME), CHECK (BALANCE >= 0) ); -- Add initial data INSERT INTO FRUIT(ID, FRUIT_NAME, PRICE) VALUES(1, 'Apple', 10); INSERT INTO FRUIT_STOCK(ID, STOCK) VALUES(1, 10); INSERT INTO ACCOUNT(USERNAME, BALANCE) VALUES('user1', 20); DELIMITER $$ -- MySQL不支持check,使用触发器来检查约束,不满足时触发异常: CREATE TRIGGER ACCOUNT_BALANCEGT0 BEFORE UPDATE ON account FOR EACH ROW BEGIN IF NEW.balance < 0 THEN -- NEW代表更新后的记录 CALL xxx_yyy(); UPDATE _xxx_yyy SET X = 1; -- 引发异常 END IF; END$$ DELIMITER ;
Maven依赖:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.26</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.1.2.RELEASE</version> </dependency>
接口:
public interface FruitShop { // fruitId - 水果ID, userName - 用户号, count - 购买数量 boolean purchase(int fruitId, String userName, int count); }
实现类:
public class JdbcFruitShop implements FruitShop { static final Logger LOGGER = LoggerFactory.getLogger(JdbcFruitShop.class); @Override public boolean purchase(int fruitId, String userName, int count) { Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); // Load the driver conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring?characterEncoding=utf8", "spring", "123456"); // Get the connection // Query the price PreparedStatement ps1 = conn.prepareStatement("SELECT PRICE FROM FRUIT WHERE ID = ?"); ps1.setInt(1, fruitId); ResultSet rs = ps1.executeQuery(); int price = 0; if (rs.next()) { price = rs.getInt(1); } ps1.close(); // Update the stock PreparedStatement ps2 = conn.prepareStatement("UPDATE FRUIT_STOCK SET STOCK = STOCK - ? WHERE ID = ?"); ps2.setInt(1, count); ps2.setInt(2, fruitId); ps2.executeUpdate(); ps2.close(); // Update the balance PreparedStatement ps3 = conn .prepareStatement("UPDATE ACCOUNT SET BALANCE = BALANCE - ? WHERE USERNAME = ?"); ps3.setInt(1, price * count); ps3.setString(2, userName); ps3.executeUpdate(); ps3.close(); } catch (SQLException e) { LOGGER.error("Purchase error:", e); } catch (ClassNotFoundException e) { LOGGER.error("driver Loading error:", e); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { LOGGER.error("Connection closing error:", e); } } } return true; } }
Spring配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <bean id="fruitShop" class="com.john.tx.service.impl.JdbcTxFruitShop"/> </beans>
测试:
@Resource FruitShop fruitShop; @Test public void test() { int fruitId = 1; String userName = "user1"; int count = 3; fruitShop.purchase(fruitId, userName, count); }
用户user1的余额是20,买了3个单价为10的苹果,余额不够支付,报错。但是数据处于不一致状态:fruit_stock表的苹果存量由10个减为7个,而账户表的余额还是20,需要使用事务。
使用JDBC的事务操作。
public class JdbcTxFruitShop implements FruitShop { @Override public boolean purchase(int fruitId, String userName, int count) { ... conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring?characterEncoding=utf8", "spring", "123456"); // Get the connection conn.setAutoCommit(false); // 取消自动提交 ... ps3.close(); conn.commit(); // 提交事务 ... } }
上面的数据源是写在代码里的,每次修改都需要重新编译,可以将其放在Spring配置中:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/spring?characterEncoding=utf8" /> <property name="username" value="spring" /> <property name="password" value="123456" /> </bean> <bean id="fruitShop" class="com.john.tx.service.impl.JdbcTxFruitShop"> <property name="dataSource" ref="dataSource" /> </bean>
public class JdbcTxFruitShop implements FruitShop { private DataSource dataSource; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } @Override public boolean purchase(int fruitId, String userName, int count) { ... conn = dataSource.getConnection(); ... } }
发表评论
-
本地事务系列之五:使用Transactional注解
2014-08-02 18:16 2840AOP的配置稍显复杂,通过@Transactional注解,同 ... -
本地事务系列之四:使用AOP
2014-08-02 17:08 914Spring AOP通过在文件中配置来管理事务,好处是对代码侵 ... -
本地事务系列之三:使用TransactionTemplate
2014-07-17 22:15 6786TransactionTemplate的灵活性好,可以给代码块 ... -
本地事务系列之二:使用PlatformTransactionManager
2014-07-17 21:37 5410Spring的事务管理器接口: public interf ... -
Spring AOP 源码系列:ProxyFactoryBean
2014-04-21 18:01 0public class ProxyFactoryBean ... -
Spring AOP 源码系列
2014-04-21 09:22 0Spring AOP通过JDK的正则表达式对Pointcut表 ... -
Spring AOP系列之五:后置通知
2014-04-14 08:59 1682和前置通知类似, 通过实现org.springframewor ... -
Spring AOP系列之四:前置通知
2014-04-13 21:28 1837通过实现org.springframework.aop.M ... -
Spring AOP系列之三:环绕代理
2014-04-13 18:20 1431通过实现org.aopalliance.intercept.M ... -
Spring AOP系列之二:Java代理
2014-04-13 18:00 1057通过Java代理的方式: 汽车的代理,需要实现java.la ... -
Spring AOP系列之一:手动方式
2014-04-13 17:44 1399AOP (Aspect Oriented Progra ... -
HibernateTemplate 使用
2014-03-03 22:09 01. queryListBySql hibernateTe ... -
Spring的组件扫描
2017-09-16 21:58 1073Spring2.0以后的版本中,引入了基于注解(Annotat ... -
ContextLoaderListener和ContextCleanupListener源码分析
2013-12-18 15:55 0public class ContextLoaderLis ... -
Cglib2AopProxy 源码分析
2013-12-05 14:30 0final class Cglib2AopProxy im ... -
Spring生命周期方法的调用顺序
2013-11-19 22:04 0Spring的几个接口: BeanFactoryAware: ... -
一、Spring AOP的简单实例
2013-11-06 23:31 17851. 往pom.xml文件添加以下依赖: <depe ... -
Spring配置中的bean引用其它bean的属性值
2013-01-23 15:24 4244这项功能在spring的3.0版本以上才支持,如果使用较早的版 ... -
spring JPA struts 整合开发(2) - spring集成struts
2012-05-20 20:55 1443一. spring JPA struts 整合开发(1) - ... -
spring JPA struts 整合开发(1) - spring集成JPA
2012-05-20 20:26 1713一. spring JPA struts 整合开发(1) - ...
相关推荐
Oracle JDBC驱动还支持高级特性,如游标、批处理操作、事务控制、存储过程调用、分布式事务等。在使用过程中,开发者可以根据需求选择合适的API进行操作。 需要注意的是,随着Oracle数据库版本的更新,新的JDBC驱动...
1. **JDBC API**: JDBC API包含了一系列的接口和类,如`java.sql.DriverManager`、`Connection`、`Statement`、`PreparedStatement`、`ResultSet`等。它们为开发者提供了与数据库交互的标准方法。 2. **JDBC的用途*...
JDBC驱动程序是实现JDBC的关键组件之一,根据其工作方式不同,可以分为以下几种类型: 1. **JDBC-ODBC桥接驱动**:这是最早的JDBC驱动类型,通过ODBC(Open Database Connectivity)接口来访问数据库。由于ODBC是一...
【JDBC连接MySQL数据库的方法浅析】 JDBC(Java Database Connectivity)...理解和熟练使用JDBC是每个Java开发者必备的技能之一。在实际项目中,开发者应根据需求选择合适的JDBC驱动类型,并注意性能优化和安全问题。
Java是世界上最流行的编程语言之一,尤其在企业级应用开发中占据主导地位。JDBC(Java Database Connectivity)是Java平台的标准接口,它允许Java程序与各种数据库进行交互。MySQL则是一种广泛使用的开源关系型...
- **DriverManager**: 这是JDBC API中的主要类之一,用于加载JDBC驱动程序并建立与数据库的连接。 - **Connection**: 表示与数据库之间的连接。一旦建立了连接,就可以执行SQL语句。 - **Statement**: 用于执行简单...
- **功能**:管理各种不同的JDBC驱动,它是JDBC API的核心类之一。 - **常用方法**: - `getConnection(String url, String username, String password)`:用于建立与数据库的连接。 - `getDrivers()`:返回已注册...
`JDBC(day01)-day05`.txt文件可能是系列教程的笔记,分别涵盖了JDBC的基础知识、连接数据库、执行SQL、事务处理、批处理等内容,逐步深入JDBC的学习。 综上所述,Java的JDBC提供了与数据库交互的标准接口,通过理解...
在Java编程中,JDBC(Java Database Connectivity)是Java平台的标准接口,用于连接各种关系型数据库。本篇文章将深入探讨Java中常用的JDBC连接数据库的方法,...熟练掌握这些基本操作,是Java开发人员必备的技能之一。
然而,在许多实际应用场景中,应用往往只需要处理单一的数据源(通常是数据库),这时使用本地事务(例如JDBC提供的事务管理功能)就足够了。 #### 二、事务管理的重要性 事务处理的核心在于确保一系列数据库操作...
综上所述,事务处理是数据库管理中的核心机制之一,通过合理设置事务的隔离级别和传播行为,可以有效解决并发操作带来的数据不一致问题。同时,针对分布式系统的特殊需求,还需要采用适当的事务管理技术,如JTA和两...
### JDBC数据访问接口详解 #### 一、JDBC概述与结构 JDBC,全称Java Database Connectivity,是Java平台上的数据库连接技术。它允许Java应用程序连接到...掌握JDBC对于任何Java开发者来说都是必不可少的技能之一。
配置连接池是确保应用服务器与数据库之间高效通信的关键步骤之一。下面详细介绍配置连接池的过程: **STEP1:** 数据库类型和驱动类型的选择。对于不同的数据库类型,需要选择合适的 JDBC 驱动。例如,如果是 ...
然后,在完成一系列操作后手动提交或回滚事务: ```java conn.commit(); // 或者 conn.rollback(); ``` #### 五、SQL语句执行方式 在JDBC中,有两种主要的方式执行SQL语句:使用`Statement`和`PreparedStatement`...
1. **Oracle**:Oracle数据库是全球最广泛使用的商业关系型数据库系统之一,由Oracle公司开发。Oracle JDBC驱动包括 Thin、OCI 和 JMS 驱动。Thin驱动是一个纯Java驱动,无需本地库,而OCI驱动需要Oracle客户端软件...
MySQL Connector/J是MySQL数据库与Java应用程序之间的桥梁,它是一个实现了Java Database Connectivity (JDBC) API的驱动程序,允许Java开发者在Java环境中访问和操作MySQL数据库。`mysql-connector-java-5.0.4.jar`...
总之,学习Java数据库连接(JDBC)是成为一名合格的Java开发者的基础技能之一,理解和掌握上述知识点,能够帮助我们有效地进行数据库操作,为后续的项目开发打下坚实的基础。随着经验的增长,你还可以深入学习更高级...
MySQL是世界上最受欢迎的关系型数据库管理系统之一,而Java作为一种广泛应用的编程语言,经常被用来与MySQL进行数据交互。在Java中,我们使用Java Database Connectivity (JDBC) API来连接和操作数据库。MySQL与Java...
JDBC是Java运行平台的核心类库之一,它提供了一系列接口,使得Java程序能够连接并操作各种类型的数据库。 9.1 JDBC简介: JDBC是Java中访问数据库的标准接口,它允许开发者编写与数据库无关的代码。这意味着,尽管...