学习心得
PreparedStatement,预编译(预加载)接口 |
1.通过conn获取的对象 |
2.是Statement接口的子接口 |
3.sql语句中可以传参,用? 来占位,通过setxxx方法给?赋值 |
4.提高性能 |
掌握情况
工具类有连接数据库还有关闭IO流,还有一些其他的操作,这样可以直接调用,省去了很多时间
总结:👓👓👓👓👓👓👓
spring的事务管理
什么是事务:逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败
事物的特性:
- 原子性:事务不可分割
- 一致性:事务执行前后数据完整性保持一致
- 隔离性:一个事务的执行不应该受到其他事务的干扰
- 持久性:一旦事务结束,数据就持久化到数据库
如果不考虑隔离性引发安全性问题
读问题
- 脏读:一个事务读到另一个事务未提交的数据
- 不可重复读:一个事务读到另一个事务已经提交的update的数据,导致一个事务中多次查询结果不一致
- 虚读,幻读:一个事务读到另一个事务已经提交的insert的数据,导致一个事务中多次查询结果不一致
写问题
丢失更新
解决读问题
设置事务的隔离级别
- Read uncommitted:未提交读,任何读问题都解决不了
- Read committed:已提交读,解决脏读,但是不可重复读和虚读有可能发生
- Repeatable read:重复读,解决脏读和不可重复读,但是虚读有可能发生
- Serializable:解决所有读问题
spring的事务管理的API
PlatformTransactionManager:平台事务管理器
平台事务管理器:接口,是spring用于管理事务的真正的对象
DataSourceTransactionManager:底层使用JDBC管理事务
HibernateTransactionManager:底层使用hibernate管理事务
TransactionDefinition:事务定义信息
事务定义:用于定义事务的相关信息,隔离级别,超时信息,传播行为,是否只读
TransactionStatus:事务的状态
事务状态:用于记录在事务管理的过程中,事务的状态的对象
事务管理的API的关系
spring进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务的管理,
在事务管理的过程中产生各种状态,将这些状态的信息记录在状态的对象中
spring的事务传播行为
spring中提供了七种事务的传播行为
保证多个操作在同一个事务中
- ROPAGATION_REQUIRED:默认值,如果A中有事务,使用A中的事务,如果A中没有,创建一个新的事务,将操作包含进来
- PROPAGATION_SUPPORTS:支持事务,如果A中有事务,使用A中的事务,如果A中没有,不使用事务
- PROPAGATION_MANDATORY:如果A中有事务,使用A中的事务,如果A中没有,抛出异常
保证多个操作不在同一个事务中
- PROPAGATION_REQUIRES_NEW:如果A中有事务,将A的事务挂起(暂停),创建新事务,只包含自身操作, 如果A中没有事务,创建一个新事务,包含自身操作
- PROPAGATION_NOT_SUPPORTED:如果A中有事务,将A中的事务挂起,不使用事务管理
- PROPAGATION_NEVER:如果A中有事务,报异常
嵌套式事务
- PROPAGATION_NESTED:嵌套事务,如果A中有事务,按照A的事务执行,执行完成后,
设置一个保存点,执行B中的操作 ,如果没有异常,执行通过,
如果有异常,可以选择回滚到 最初位置,也可以回滚到保存点
spring事务的传播行为的用途
如果遇到了特别复杂的业务逻辑,有可能出现业务层之间的方法相互调用
事物的传播行为主要用来解决业务层方法相互调用的问题
spring的事务管理
第一类:编程式事务管理(需要手动编写代码)
第二类:声明式事务管理(通过配置实现)--AOP
XML方式的声明式事务管理
注解方式的声明式事务管理
mybatis:本是apache的一个开源项目ibatis,2010年迁移到google code ,并且改名为mybatis,
2013年11月迁移到Github
面向sql的持久层框架,他封装了JDBC访问数据库的的过程,我们开发,只需专注于sql语句本身的拼装,
其他复杂的过程全部可以交给mybaties去完成
mybatis就是类似于hibernate的ORM的持久层框架
ORM:对象关系映射,是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术
练习
工具类:
package com.jsoft.util; import com.jsoft.morning.Ch01; import java.io.IOException; import java.sql.*; import java.util.Objects; import java.util.Properties; public class JDBCUtil { public static void close(Connection conn, Statement stmt) { if (Objects.nonNull(stmt)) { try { stmt.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if (Objects.nonNull(conn)) { try { conn.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } public static Connection connection() { /* 使用属性文件的好处: 1、实现了代码和数据的分离,如果需要修改配置信息,直接在属性文件中修改即可,不需要深入代码 2、如果修改了配置信息,省去了编译的过程 */ Properties properties = new Properties(); // 读取外部的properties属性文件 // 记住就好,复制粘贴就好 try { properties.load(Ch01.class.getClassLoader().getResourceAsStream("jdbc.properties")); } catch (IOException e) { throw new RuntimeException(e); } String url = properties.getProperty("mysql.url"); String driverName = properties.getProperty("mysql.driverName"); String username = properties.getProperty("mysql.username"); String password = properties.getProperty("mysql.password"); // // 1.加载驱动类 try { Class.forName(driverName); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } // // 4.获取连接 Connection connection = null; try { connection = DriverManager.getConnection(url, username, password); } catch (SQLException e) { throw new RuntimeException(e); } return connection; } public static void close(Connection conn, Statement stmt, ResultSet rs) { if(Objects.nonNull(stmt)) { try { stmt.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if(Objects.nonNull(conn)){ try { conn.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if(Objects.nonNull(rs)){ try { rs.close(); } catch (SQLException e) { throw new RuntimeException(e); } }
先在navicat里面建一个表,银行信息的,有id,还有账户,余额
然后还有Account类,构造器传参
public class Account { private Integer id; private String accountid; private Double balance; public Account() { } public Account(Integer id, String accountid, Double balance) { this.id = id; this.accountid = accountid; this.balance = balance; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getAccountid() { return accountid; } public void setAccountid(String accountid) { this.accountid = accountid; } public Double getBalance() { return balance; } public void setBalance(Double balance) { this.balance = balance
然后就是写一个全是方法的类,包括查询,转账。。。
import com.jsoft.util.JDBCUtil; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class AccountDao { private final Connection conn; { conn = JDBCUtil.connection(); } /** * 转账 */ public Integer transform(String out,String in,Double balance){ // 取款之前要先查询 ResultSet rs = null; PreparedStatement preparedStatement = null; PreparedStatement preparedStatement2 = null; double b = 0; String sql = "select balance from bank where accountid = ?"; try { preparedStatement = conn.prepareStatement(sql); preparedStatement.setString(1,out); rs = preparedStatement.executeQuery(); while(rs.next()) { b = rs.getDouble("balance"); } if(b >= balance) { // 余额够 // 执行修改 conn.setAutoCommit(false); sql = "update bank set balance = balance - ? where accountid = ?"; preparedStatement = conn.prepareStatement(sql); preparedStatement.setDouble(1,balance); preparedStatement.setString((int)2,out); int i = preparedStatement.executeUpdate(); sql = "update bank set balance = balance + ? where accountid = ?"; preparedStatement2 = conn.prepareStatement(sql); preparedStatement2.setDouble(1,balance); preparedStatement2.setString((int)2,in); i = preparedStatement2.executeUpdate(); conn.commit(); return i; }else{ // 余额不够 throw new RuntimeException("余额不足,转账失败"); } } catch (SQLException e) { try { conn.rollback(); } catch (SQLException ex) { throw new RuntimeException(ex); } throw new RuntimeException(e); } finally { JDBCUtil.close(conn,preparedStatement,rs); JDBCUtil.close(null,preparedStatement2); } } /** * 取款 */ public Integer out(String accountid,Double balance) { // 取款之前要先查询 ResultSet rs = null; PreparedStatement preparedStatement = null; double b = 0; String sql = "select balance from bank where accountid = ?"; try { preparedStatement = conn.prepareStatement(sql); preparedStatement.setString(1,accountid); rs = preparedStatement.executeQuery(); while(rs.next()) { b = rs.getDouble("balance"); } if(b >= balance) { // 余额够 // 执行修改 sql = "update bank set balance = balance - ? where accountid = ?"; preparedStatement = conn.prepareStatement(sql); preparedStatement.setDouble(1,balance); preparedStatement.setString((int)2,accountid); int i = preparedStatement.executeUpdate(); return i; }else{ // 余额不够 throw new RuntimeException("余额不足,取款失败"); } } catch (SQLException e) { throw new RuntimeException(e); } finally { JDBCUtil.close(conn,preparedStatement,rs); } } /** * 存款 * @param accountid * @param balance * @return */ public Integer in(String accountid,Double balance) { int i = 0; String sql = "update bank set balance = ? where accountid = ?"; PreparedStatement preparedStatement = null; try { preparedStatement = conn.prepareStatement(sql); preparedStatement.setDouble(1,balance); preparedStatement.setString(2,accountid); i = preparedStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } finally { JDBCUtil.close(conn,preparedStatement); } return i; } /** * 开户 * @param accountid * @param balance * @return */ public Integer add(String accountid,Double balance) { int i = 0; String sql = "insert into bank (accountid,balance) values (?,?)"; PreparedStatement preparedStatement = null; try { preparedStatement = conn.prepareStatement(sql); preparedStatement.setString(1,accountid); preparedStatement.setDouble(2,balance); i = preparedStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); } finally { JDBCUtil.close(conn,preparedStatement); }
测试功能
1、创建一张银行信息表
字段:主键 银行卡号,余额......
2、封装方法,存款,取款,转账,所有的操作最终要数据持久化。
3、查询余额的方法。
4、开户、修改
用什么就调用什么
import org.junit.Test; public class Demo { private AccountDao accountDao = new AccountDao(); @Test public void test01() { // System.out.println(accountDao.out("1102345678", 2000.00)); accountDao.transform("1102345678","1209876543",10000.00); }