day45_Pool&JDBCTemplate

  • jdbc事务
  • 连接池概念
  • C3P0
  • Driud
  • JDBC Template

JDBC事务控制

​ 事务是一个包含多个步骤或者业务操作。如果这个业务或者多个步骤被事务管理,则这多个步骤要么同时成功,要么回滚,这多个步骤是一个整体,不可分割

​ 操作:开启事务:start transaction

​ 提交事务:commit

​ 回滚事务:roolback

​ 在JDBC中,使用Connection对象管理事务

​ 开启事务:setAutoCommitc(boolean autoCommit):执行该方法里面传入 false时,手动开启事务 --->在执行sql之前开启事务

​ 提交事务:commit(); --->当所有的sql语句执行完毕 提交事务

​ 回滚事务:rollback();--->当事务中发生异常时,回滚事务,放在catch语句块中

	private static PreparedStatement ps01 = null;
	private static PreparedStatement ps02 = null;
	
	public static void main(String[] args) {

	}

	// 带事务的转账
	public static void transform() {
		// 张三转给李四10000

		// 定义实现转账的两条sql
		double money = 10000;
		String username01 = "张三";
		String username02 = "李四";

		String sql01 = "update account set balance =balance-? where username=?";
		String sql02 = "update account set balance =balance+? where username=?";
		
		//获取Connection对象以用来手动开启事务 setAutoCommit()
		Connection con = DBUtil.getConnection();
		
		try {
			
			//让张三的钱减少10000
			con.setAutoCommit(false);
			//通过con获取预处理执行对象
			ps01 = con.prepareStatement(sql01);
			ps01.setDouble(1, money);
			ps01.setString(2, username01);
			//执行sql语句
			int count01 = ps01.executeUpdate();//获取影响记录条数
			
			//手动制造异常 int i = 1 / 0; 
			
			//让李四的钱增加10000
			ps02 = con.prepareStatement(sql02);
			ps02.setDouble(1, money);
			ps02.setString(2, username02);
			//执行sql语句
			int count02 = ps02.executeUpdate();//获取影响记录条数
			
			//提交事务
			con.commit();
			System.out.println("转账成功");
			
		} catch (Exception e) {
			//发生异常   事务回滚
			try {
				con.rollback();
				System.out.println("转账失败");
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();			
		}finally {
			//释放连接
			try {
				ps02.close();
				ps01.close();
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}
	}

连接池

​ 什么是连接池?

​ 其实就是一个容器,与线程池概念相似,在这个容器中存放了多个连接对象,当 系统开始运行时,可以让系统提前创建多个连接对象,放到连接中,当客户端需要连 接对象时,可以从连接池中申请一个连接去访问数据库,当连接使用完毕时,不再释 放归资源,而是把这个连接对象归还给连接池

​ 优点:

​ 大大节省系统开销

​ 提高访问速度

​ 实现操作:

javax.sql 操作数据库额外功能包

​ JNDI: java naming and directory interface java命名和目录接口

​ 使用JNDI降低程序和数据库之间的耦合度,使你的程序更加方便的配置

​ 是JavaEE规范中的重要规范之一 。 是EJB相关知识

​ 将大量暴露在外部的代码放入DataSource,通过它来管理控制

​ DataSource接口里并不提供具体的实现,而是由驱动程序供应商(数据库厂 商)提供

​ 1.c3p0是数据库连接池的一套技术

​ 2.druid

c3p0:数据库连接池技术

​ 步骤:

  1. ​ 准备jar包c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar

  2. ​ 植入到工程的classpath下

  3. ​ 定义配置文件:

    ​ 文件类型:c3p0.properti 或者 c3p0-config.xml

    ​ 路径:放到classpath类路径下(build--->classes文件下) 对于工程 来说直接放到src下(直接会被解析到build--->classes下)

  4. ​ 获取DataSource对象:数据库连接池对象 通过实例化 CombopooledDataSource来获取

  5. ​ 从连接池中获取连接对象 getConnection()

druid:数据库连接池技术

​ 步骤:

  1. ​ 准备jar包druid-1.0.9.jar
  2. ​ 定义配置文件:使用properties文件类型,名字随便起
  3. ​ 手动加载配置文件信息:Properties集合
  4. ​ 获取DataSource对象:数据库连接池对象 通过工厂方式实现 DruidDataSourceFactory
  5. ​ 从连接池中获取连接对象 getConnection()

JDBC Template

将获取连接对象和执行对象隐藏到内部,直接获取数据源就可以对数据库操作

  • Spring框架提供了对JDBC操作的简单封装,使用JDBCTemplate对象来简化JDBC开发流程。

  • 步骤:

    • 从官网下载对应的spring-jdbc相关的jar包,导入工程类路径下,放到lib文件夹下面即可

    • 创建JDBCTemplate对象。依赖于DataSouce连接池(数据源)

    • 使用JDBCTemplate对象中的api方法实现crud操作

      • DML操作: update()

      • DQL操作: 查询 不用select,使用query

        • query(): 将查询的结果集封装成JavaBean对象

          • query()方法的参数:RowMapper

            • 手动装配:使用匿名内部类,自定义装配查询的每条记录值

              List<Account> list = tp.query(sql, new RowMapper<Account>() {
              
              			@Override
              			public Account mapRow(ResultSet set, int arg1) throws SQLException {
              				//封装查询到每一条记录值
              				Account account = new Account();
              				account.setId(set.getInt(1));
              				account.setUsername(set.getString(2));
              				account.setBalance(set.getDouble(3));
              				return account;
              			}
              		});
              
            • 自动装配:使用Spring提供的BeanPropertyRowMapper实现类,完成对数据的自动装配

              具体操作-->new BeanPropertyRowMapper<类型>(类型.class)

        • queryForMap(): 将查询的结果集封装成map集合,只能封装一条记录:键key是字段名,值value是字段值,结果集记录数只能是1

        • queryForList():将结果集封装成List集合,在list集合中有多条记录,每一条记录都是一个map集合

          List<Map<Object,Object>> list ;

          • queryFoObject():将结果集封装成一个对象,一般用于聚合函数 查询总记录数 int count()a
      • 具体操作:

           // 增删改动作
           // 修改数据
        	public static void modifyData() {
        		
        		int count = jdbcTemplate.update("update account set username = ? where username = ?", "小五","王五");
        		System.out.println(count);
        	}
        	// 删除数据
        	public static void deleteData() {
        		int count = jdbcTemplate.update("delete from account where username = ?", "小五");
        		System.out.println(count);
        	}
        	// 插入一条数据
        	public static void insertDate() {
        		int count = jdbcTemplate.update("insert into account values(null,?,?)", "王五",5000);
        		System.out.println(count);
        	}
        	public static void test() {
        		// 查询张三的这条信息 封装到账户对象中
        		String username = "张三";
        		String sql = "select * from account where username = ?";	
        		Map<String, Object> map = jdbcTemplate.queryForMap(sql,username);
        		System.out.println(map);// {id=1, username=张三, balance=20000.0}
        	}
        	
        	// 简化手动封装的方法
        	public static void queryAll() {
        		String sql = "select * from account";
        		// Incorrect column count: expected 1, actual 3
        		List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
        		System.out.println(list);
        		
        	}
        	
        	// 使用query方法优化queryBean方法
        	public static void queryBean2() {
        		List<Account> list = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
        		System.out.println(list);
        		
        	}
        	
        	// 将查询到结果集封装成JavaBean对象
        	public static void queryBean() {
        		String sql = "select * from account where username = '张三'";
        		// RowMapper<T>
        		List<Account> list = jdbcTemplate.query(sql, new RowMapper<Account>() {
        			@Override
        			public Account mapRow(ResultSet set, int arg1) throws SQLException {
        				// 封装查询到每一条记录值
        				Account account = new Account();
        				int id = set.getInt(1);
        				String username = set.getString(2);
        				double balance = set.getDouble(3);
        				account.setId(id);
        				account.setUsername(username);
        				account.setBalance(balance);
        				return account;
        			}
        		});
        		
        		System.out.println(list);// [Account [id=1, username=张三, balance=20000.0]]
        	}
        	
        	// 查询总记录   查询account表中的所有记录数
        	public static void queryTotalNum() {
        		// queryFoObject()
        		Integer count = jdbcTemplate.queryForObject("select count(*) from account", Integer.class);
        		System.out.println(count);// 4
        	}
        
原文地址:https://www.cnblogs.com/mitoris/p/14248319.html