Transaction 其实指的一组操做,里面包含许多个单一的逻辑。只要有一个逻辑没有执行成功,那么都算失败。 全部的数据都回归到最初的状态(回滚)java
为了确保逻辑的成功。 例子: 银行的转帐。mysql
开启事务程序员
start transaction;web
提交或者回滚事务sql
commit; 提交事务, 数据将会写到磁盘上的数据库 rollback ; 数据回滚,回到最初的状态。数据库
关闭自动提交功能。apache
代码里面的事务,主要是针对链接来的。编程
经过conn.setAutoCommit(false )来关闭自动提交的设置。数组
提交事务 conn.commit();tomcat
回滚事务 conn.rollback();
@Test public void testTransaction(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConn(); //链接,事务默认就是自动提交的。 关闭自动提交。 conn.setAutoCommit(false); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); //扣钱, 扣ID为1 的100块钱 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); int a = 10 /0 ; //加钱, 给ID为2 加100块钱 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); //成功: 提交事务。 conn.commit(); } catch (SQLException e) { try { //事变: 回滚事务 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtil.release(conn, ps, rs); } }
指的是 事务中包含的逻辑,不可分割。
指的是 事务执行先后。数据完整性
指的是 事务在执行期间不该该受到其余事务的影响
指的是 事务执行成功,那么数据应该持久保存到磁盘上。
不考虑隔离级别设置,那么会出现如下问题。
脏读 不可重读读 幻读.
* 脏读 > 一个事务读到另一个事务还未提交的数据 * 不可重复读 > 一个事务读到了另一个事务提交的数据 ,形成了先后两次查询结果不一致。
设置A窗口的隔离级别为 读未提交
两个窗口都分别开启事务
丢失更新
这个隔离级别可以屏蔽 脏读的现象, 可是引起了另外一个问题 ,不可重复读。
若是有一个链接的隔离级别设置为了串行化 ,那么谁先打开了事务, 谁就有了先执行的权利, 谁后打开事务,谁就只能得着,等前面的那个事务,提交或者回滚后,才能执行。 可是这种隔离级别通常比较少用。 容易形成性能上的问题。 效率比较低。
读未提交 > 读已提交 > 可重复读 > 可串行化
可串行化 > 可重复读 > 读已提交 > 读未提交
在代码里面会使用事务
conn.setAutoCommit(false); conn.commit(); conn.rollback();
事务只是针对链接链接对象,若是再开一个链接对象,那么那是默认的提交。
事务是会自动提交的。
读 脏读 一个事务读到了另外一个事务未提交的数据 不可重复读 一个事务读到了另外一个事务已提交的数据,形成先后两次查询结果不一致 幻读 一个事务读到了另外一个事务insert的数据 ,形成先后查询结果不一致 。 写 丢失更新。
读未提交
引起问题: 脏读
读已提交
解决: 脏读 , 引起: 不可重复读
可重复读
解决: 脏读 、 不可重复读 , 未解决: 幻读
可串行化
解决: 脏读、 不可重复读 、 幻读。
mySql 默认的隔离级别是 可重复读
Oracle 默认的隔离级别是 读已提交
能够在查询的时候,加入 for update
要求程序员本身控制。
- 数据库的链接对象建立工做,比较消耗性能。
2.一开始如今内存中开辟一块空间(集合) , 一开先往池子里面放置 多个链接对象。 后面须要链接的话,直接从池子里面去。不要去本身建立链接了。 使用完毕, 要记得归还链接。确保链接对象能循环利用。
代码实现
出现的问题:
须要额外记住 addBack方法
单例。
没法面向接口编程。
UserDao dao = new UserDaoImpl(); dao.insert();
DataSource dataSource = new MyDataSource();
由于接口里面没有定义addBack方法。
怎么解决? 以addBack 为切入点。
因为多了一个addBack 方法,因此使用这个链接池的地方,须要额外记住这个方法,而且还不能面向接口编程。
咱们打算修改接口中的那个close方法。 原来的Connection对象的close方法,是真的关闭链接。 打算修改这个close方法,之后在调用close, 并非真的关闭,而是归还链接对象。
原有的方法逻辑,不是咱们想要的。 想修改本身的逻辑
直接改源码 没法实现。
继承, 必须得知道这个接口的具体实现是谁。
使用装饰者模式。
导入jar文件
不使用配置文件:
public void testDBCP01(){ Connection conn = null; PreparedStatement ps = null; try { //1. 构建数据源对象 BasicDataSource dataSource = new BasicDataSource(); //连的是什么类型的数据库, 访问的是哪一个数据库 , 用户名, 密码。。 //jdbc:mysql://localhost/bank 主协议:子协议 ://本地/数据库 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost/bank"); dataSource.setUsername("root"); dataSource.setPassword("root"); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admin"); ps.setInt(2, 1000); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } }
使用配置文件方式:
Connection conn = null; PreparedStatement ps = null; try { BasicDataSourceFactory factory = new BasicDataSourceFactory(); Properties properties = new Properties(); InputStream is = new FileInputStream("src//dbcpconfig.properties"); properties.load(is); DataSource dataSource = factory.createDataSource(properties); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "liangchaowei"); ps.setInt(2, 100); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); }
C3P0
拷贝jar文件 到 lib目录
Connection conn = null; PreparedStatement ps = null; try { //1. 建立datasource ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 设置链接数据的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); //忘记了---> 去之前的代码 ---> jdbc的文档 dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("root"); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); }
//默认会找 xml 中的 default-config 分支。 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 设置链接数据的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); //忘记了---> 去之前的代码 ---> jdbc的文档 dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("root"); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200);
//dbutils 只是帮咱们简化了CRUD 的代码, 可是链接的建立以及获取工做。 不在他的考虑范围 QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); //增长 //queryRunner.update("insert into account values (null , ? , ? )", "aa" ,1000); //删除 //queryRunner.update("delete from account where id = ?", 5); //更新 //queryRunner.update("update account set money = ? where id = ?", 10000000 , 6);
直接new接口的匿名实现类
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>(){ @Override public Account handle(ResultSet rs) throws SQLException { Account account = new Account(); while(rs.next()){ String name = rs.getString("name"); int money = rs.getInt("money"); account.setName(name); account.setMoney(money); } return account; } }, 6); System.out.println(account.toString());
直接使用框架已经写好的实现类。
查询单个对象
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); //查询单个对象 Account account = queryRunner.query("select * from account where id = ?", new BeanHandler(Account.class), 8);
查询多个对象
QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); Listlist = queryRunner.query("select * from account ", new BeanListHandler(Account.class));
如下两个是使用频率最高的
BeanHandler, 查询到的单个数据封装成一个对象 BeanListHandler, 查询到的多个数据封装 成一个List<对象>
ArrayHandler, 查询到的单个数据封装成一个数组 ArrayListHandler, 查询到的多个数据封装成一个集合 ,集合里面的元素是数组。 MapHandler, 查询到的单个数据封装成一个map MapListHandler,查询到的多个数据封装成一个集合 ,集合里面的元素是map。
ColumnListHandler KeyedHandler ScalarHandler
使用命令行演示 使用代码演示
脏读、
不可重复读、
幻读 丢失更新
悲观锁 乐观锁 4个隔离级别 读未提交 读已提交 可重复读 可串行化
DBCP
不使用配置
使用配置
C3P0
不使用配置
使用配置 (必须掌握)
自定义链接池
装饰者模式
简化了咱们的CRUD , 里面定义了通用的CRUD方法。
queryRunner.update(); queryRunner.query
driverClass=com.mysql.jdbc.Driver url=jdbc:mysql://localhost/bank name=root password=root
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- default-config 默认的配置, --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost/bank</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> <!-- This app is massive! --> <named-config name="oracle"> <property name="acquireIncrement">50</property> <property name="initialPoolSize">100</property> <property name="minPoolSize">50</property> <property name="maxPoolSize">1000</property> <!-- intergalactoApp adopts a different approach to configuring statement caching --> <property name="maxStatements">0</property> <property name="maxStatementsPerConnection">5</property> <!-- he's important, but there's only one of him --> <user-overrides user="master-of-the-universe"> <property name="acquireIncrement">1</property> <property name="initialPoolSize">1</property> <property name="minPoolSize">1</property> <property name="maxPoolSize">5</property> <property name="maxStatementsPerConnection">50</property> </user-overrides> </named-config> </c3p0-config>
#链接设置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/bank username=root password=root #<!-- 初始化链接 --> initialSize=10 #最大链接数量 maxActive=50 #<!-- 最大空闲链接 --> maxIdle=20 #<!-- 最小空闲链接 --> minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --> maxWait=60000 #JDBC驱动创建链接时附带的链接属性属性的格式必须为这样:[属性名=property;] #注意:"user" 与 "password" 两个属性会被明确地传递,所以这里不须要包含他们。 connectionProperties=useUnicode=true;characterEncoding=gbk #指定由链接池所建立的链接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由链接池所建立的链接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
c3p0
package com.itheima.c3p0; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.dbcp.BasicDataSource; import org.junit.Test; import com.itheima.uitl.JDBCUtil; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Demo { @Test public void testC3P0 (){ Connection conn = null; PreparedStatement ps = null; try { //1. 建立datasource // ComboPooledDataSource dataSource = new ComboPooledDataSource("oracle"); //默认会找 xml 中的 default-config 分支。 ComboPooledDataSource dataSource = new ComboPooledDataSource(); System.out.println(dataSource.hashCode() ); ComboPooledDataSource dataSource2 = new ComboPooledDataSource(); System.out.println(dataSource2.hashCode()+"-------"); //2. 设置链接数据的信息 dataSource.setDriverClass("com.mysql.jdbc.Driver"); //忘记了---> 去之前的代码 ---> jdbc的文档 dataSource.setJdbcUrl("jdbc:mysql://localhost/bank"); dataSource.setUser("root"); dataSource.setPassword("root"); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admi234n"); ps.setInt(2, 103200); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.c3p0; import java.sql.Connection; import java.sql.PreparedStatement; import org.junit.Test; import com.itheima.uitl.JDBCUtil; import com.mchange.v2.c3p0.ComboPooledDataSource; public class C3P0Demo02 { @Test public void testC3P0(){ Connection conn = null; PreparedStatement ps = null; try { //就new了一个对象。 ComboPooledDataSource dataSource = new ComboPooledDataSource(); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "wangwu2"); ps.setInt(2, 2600); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.c3p0; import java.sql.Connection; import java.sql.SQLException; import com.itheima.uitl.JDBCUtil; import com.itheima.uitl.JDBCUtil02; public class Test { public static void main(String[] args) { try { Connection conn = JDBCUtil02.getConn(); conn.prepareStatement(null); } catch (SQLException e) { e.printStackTrace(); } } }
package com.itheima.dbcp; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import org.apache.commons.dbcp.BasicDataSource; import org.junit.Test; import com.itheima.uitl.JDBCUtil; public class DBCPDemo { @Test public void testDBCP01(){ Connection conn = null; PreparedStatement ps = null; try { //1. 构建数据源对象 BasicDataSource dataSource = new BasicDataSource(); //连的是什么类型的数据库, 访问的是哪一个数据库 , 用户名, 密码。。 // jdbc:mysql://localhost/bank 主协议:子协议 ://本地/数据库 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost/bank"); dataSource.setUsername("root"); dataSource.setPassword("root"); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "admin"); ps.setInt(2, 1000); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.dbcp; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Properties; import java.util.ResourceBundle; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import org.junit.Test; import com.itheima.uitl.JDBCUtil; public class DBCPDemo02 { @Test public void testDBCP02(){ /*BasicDataSource dataSource = new BasicDataSource(); //不知道这行能不能实现。 dataSource.setConnectionProperties("dbcpconfig.properties");*/ //ResourceBundle bundler = ResourceBundle.getBundle(baseName); Connection conn = null; PreparedStatement ps = null; try { BasicDataSourceFactory factory = new BasicDataSourceFactory(); Properties properties = new Properties(); // InputStream is = new FileInputStream("src//dbcpconfig.properties"); InputStream is = getClass().getClassLoader().getResourceAsStream("dbcpconfig.properties"); properties.load(is); DataSource dataSource = factory.createDataSource(properties); //2. 获得链接对象 conn = dataSource.getConnection(); String sql = "insert into account values(null , ? , ?)"; ps = conn.prepareStatement(sql); ps.setString(1, "liangchaowei22"); ps.setInt(2, 200); ps.executeUpdate(); } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps); } } }
package com.itheima.dbutils; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.junit.Test; import com.itheima.domain.Account; import com.mchange.v2.c3p0.ComboPooledDataSource; /* //针对增长 、 删除 、 修改 queryRunner.update(sql) //针对查询 queryRunner.query(sql, rsh);*/ public class TestDBUtils { @Test public void testInsert() throws SQLException, InstantiationException, IllegalAccessException{ // ComboPooledDataSource dataSource = new ComboPooledDataSource(); //dbutils 只是帮咱们简化了CRUD 的代码, 可是链接的建立以及获取工做。 不在他的考虑范围 QueryRunner queryRunner = new QueryRunner(new ComboPooledDataSource()); //增长 //queryRunner.update("insert into account values (null , ? , ? )", "aa" ,1000); //删除 // queryRunner.update("delete from account where id = ?", 5); //更新 //queryRunner.update("update account set money = ? where id = ?", 10000000 , 6); //去执行查询,查询到的数据仍是在哪一个result里面。 而后调用下面的handle方法,由用户手动去封装。 /*Account account = queryRunner.query("select * from account where id = ?", new ResultSetHandler<Account>(){ @Override public Account handle(ResultSet rs) throws SQLException { Account account = new Account(); while(rs.next()){ String name = rs.getString("name"); int money = rs.getInt("money"); account.setName(name); account.setMoney(money); } return account; } }, 6); System.out.println(account.toString()); */ // 经过类的字节码获得该类的实例 /* Account a = new Account(); //建立一个类的实例。 Account a1= Account.class.newInstance(); */ //查询单个对象 Account account = queryRunner.query("select * from account where id = ?", new BeanHandler<Account>(Account.class), 8); System.out.println(account.toString()); /*List<Account> list = queryRunner.query("select * from account ", new BeanListHandler<Account>(Account.class)); for (Account account : list) { System.out.println(account.toString()); }*/ } }
package com.itheima.domain; public class Account { private String name02; private int money; public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public String getName02() { return name02; } public void setName02(String name02) { this.name02 = name02; } @Override public String toString() { return "Account [name02=" + name02 + ", money=" + money + "]"; } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一个属性配置对象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用类加载器,去读取src底下的资源文件。 后面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //导入输入流。 properties.load(is); //读取属性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 获取链接对象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 创建链接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; import com.mchange.v2.c3p0.ComboPooledDataSource; public class JDBCUtil02 { static ComboPooledDataSource dataSource = null; static{ dataSource = new ComboPooledDataSource(); } /** * 获取链接对象 * @return * @throws SQLException */ public static Connection getConn() throws SQLException{ return dataSource.getConnection(); } /** * 释放资源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.uitl; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import javax.sql.DataSource; /** * 这是一个数据库链接池 * 一开始先往池子里面放10个链接 * * 1. 开始建立10个链接。 * * 2. 来的程序经过getConnection获取链接 * * 3. 用完以后,使用addBack 归还链接。 * * 4. 扩容。 * * * 问题: * * 1. sun公司针对数据库链接池定义的一套规范。 * * 1. 须要额外记住 addBack方法 * * 2. 单例。 * * 3. 没法面向接口编程。 * * UserDao dao = new UserDaoImpl(); * dao.insert(); * * * DataSource dataSource = new MyDataSource(); * * 由于接口里面没有定义addBack方法。 * * 4. 怎么解决? * */ public class MyDataSource implements DataSource { List <Connection> list = new ArrayList<Connection>(); public MyDataSource() { for (int i = 0; i < 10; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } // 该链接池对外公布的获取链接的方法 @Override public Connection getConnection() throws SQLException { //来拿链接的时候,先看看,池子里面还有没有。 if(list.size() == 0 ){ for (int i = 0; i < 5; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } //remove(0) ---> 移除第一个。 移除的是集合中的第一个。 移除的是开始的那个元素 Connection conn = list.remove(0); return conn; } /** * 用完以后,记得归还。 * @param conn */ public void addBack(Connection conn){ list.add(conn); } //---------------------------- @Override public PrintWriter getLogWriter() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setLogWriter(PrintWriter out) throws SQLException { // TODO Auto-generated method stub } @Override public void setLoginTimeout(int seconds) throws SQLException { // TODO Auto-generated method stub } @Override public int getLoginTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { // TODO Auto-generated method stub return null; } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Connection getConnection(String username, String password) throws SQLException { // TODO Auto-generated method stub return null; } }
package com.itheima.uitl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.Test; public class TestPool { @Test public void testPool(){ Connection conn = null; PreparedStatement ps = null; MyDataSource dataSource = new MyDataSource(); try { conn = dataSource.getConnection(); String sql = "insert into account values (null , 'xilali' , 10)"; ps = conn.prepareStatement(sql); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } //归还链接 //conn.close(); dataSource.addBack(conn); //JDBCUtil.release(conn, st, rs); } } }
package com.itheima.uitl; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; import java.sql.Struct; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; public class ConnectionWrap implements Connection{ Connection connection = null; List <Connection> list ; public ConnectionWrap(Connection connection , List <Connection> list) { super(); this.connection = connection; this.list = list; } @Override public void close() throws SQLException { //connection.close(); System.out.println("有人来归还链接对象了。 归还以前,池子里面是:"+list.size()); list.add(connection); System.out.println("有人来归还链接对象了。 归还以后...,池子里面是:"+list.size()); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return connection.prepareStatement(sql); } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Statement createStatement() throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql) throws SQLException { // TODO Auto-generated method stub return null; } @Override public String nativeSQL(String sql) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setAutoCommit(boolean autoCommit) throws SQLException { // TODO Auto-generated method stub } @Override public boolean getAutoCommit() throws SQLException { // TODO Auto-generated method stub return false; } @Override public void commit() throws SQLException { // TODO Auto-generated method stub } @Override public void rollback() throws SQLException { // TODO Auto-generated method stub } @Override public boolean isClosed() throws SQLException { // TODO Auto-generated method stub return false; } @Override public DatabaseMetaData getMetaData() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setReadOnly(boolean readOnly) throws SQLException { // TODO Auto-generated method stub } @Override public boolean isReadOnly() throws SQLException { // TODO Auto-generated method stub return false; } @Override public void setCatalog(String catalog) throws SQLException { // TODO Auto-generated method stub } @Override public String getCatalog() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setTransactionIsolation(int level) throws SQLException { // TODO Auto-generated method stub } @Override public int getTransactionIsolation() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public SQLWarning getWarnings() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void clearWarnings() throws SQLException { // TODO Auto-generated method stub } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Map<String, Class<?>> getTypeMap() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException { // TODO Auto-generated method stub } @Override public void setHoldability(int holdability) throws SQLException { // TODO Auto-generated method stub } @Override public int getHoldability() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public Savepoint setSavepoint() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Savepoint setSavepoint(String name) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void rollback(Savepoint savepoint) throws SQLException { // TODO Auto-generated method stub } @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { // TODO Auto-generated method stub } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Clob createClob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Blob createBlob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public NClob createNClob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public SQLXML createSQLXML() throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isValid(int timeout) throws SQLException { // TODO Auto-generated method stub return false; } @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { // TODO Auto-generated method stub } @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { // TODO Auto-generated method stub } @Override public String getClientInfo(String name) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Properties getClientInfo() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setSchema(String schema) throws SQLException { // TODO Auto-generated method stub } @Override public String getSchema() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void abort(Executor executor) throws SQLException { // TODO Auto-generated method stub } @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { // TODO Auto-generated method stub } @Override public int getNetworkTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一个属性配置对象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用类加载器,去读取src底下的资源文件。 后面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //导入输入流。 properties.load(is); //读取属性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 获取链接对象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 创建链接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.uitl; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import javax.sql.DataSource; /** * 这是一个数据库链接池 * 一开始先往池子里面放10个链接 * * 1. 开始建立10个链接。 * * 2. 来的程序经过getConnection获取链接 * * 3. 用完以后,使用addBack 归还链接。 * * 4. 扩容。 * * * 问题: * * 1. sun公司针对数据库链接池定义的一套规范。 * * 1. 须要额外记住 addBack方法 * * 2. 单例。 * * 3. 没法面向接口编程。 * * UserDao dao = new UserDaoImpl(); * dao.insert(); * * * DataSource dataSource = new MyDataSource(); * * 由于接口里面没有定义addBack方法。 * * 4. 怎么解决? * */ public class MyDataSource implements DataSource { List <Connection> list = new ArrayList<Connection>(); public MyDataSource() { for (int i = 0; i < 10; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } // 该链接池对外公布的获取链接的方法 @Override public Connection getConnection() throws SQLException { //来拿链接的时候,先看看,池子里面还有没有。 if(list.size() == 0 ){ for (int i = 0; i < 5; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } //remove(0) ---> 移除第一个。 移除的是集合中的第一个。 移除的是开始的那个元素 Connection conn = list.remove(0); //在把这个对象抛出去的时候, 对这个对象进行包装。 Connection connection = new ConnectionWrap(conn, list); return connection; } /** * 用完以后,记得归还。 * @param conn */ public void addBack(Connection conn){ list.add(conn); } //---------------------------- @Override public PrintWriter getLogWriter() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setLogWriter(PrintWriter out) throws SQLException { // TODO Auto-generated method stub } @Override public void setLoginTimeout(int seconds) throws SQLException { // TODO Auto-generated method stub } @Override public int getLoginTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { // TODO Auto-generated method stub return null; } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Connection getConnection(String username, String password) throws SQLException { // TODO Auto-generated method stub return null; } }
package com.itheima.uitl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.Test; public class TestPool { @Test public void testPool(){ Connection conn = null; PreparedStatement ps = null; MyDataSource dataSource = new MyDataSource(); try { conn = dataSource.getConnection(); String sql = "insert into account values (null , 'xilali' , 10)"; ps = conn.prepareStatement(sql); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } //归还链接 //conn.close(); //dataSource.addBack(conn); JDBCUtil.release(conn, ps); } } }
package com.itheima.jdbc.util; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一个属性配置对象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用类加载器,去读取src底下的资源文件。 后面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //导入输入流。 properties.load(is); //读取属性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 获取链接对象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 创建链接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st ){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.jdbc.test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import com.itheima.jdbc.util.JDBCUtil; public class MainTest { public static void main(String[] args) { //查询 Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 获取链接对象 conn = JDBCUtil.getConn(); //2. 根据链接对象,获得statement st = conn.createStatement(); //3. 执行sql语句,返回ResultSet String sql = "select * from t_stu"; rs= st.executeQuery(sql); //4. 遍历结果集 while(rs.next()){ String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(name+" " + age); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } } }
package com.itheima.jdbc.test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import com.itheima.jdbc.util.JDBCUtil; /** * 使用junit执行单元测试 */ public class TestDemo { @Test public void testQuery() { // 查询 Connection conn = null; Statement st = null; ResultSet rs = null; try { // 1. 获取链接对象 conn = JDBCUtil.getConn(); // 2. 根据链接对象,获得statement st = conn.createStatement(); // 3. 执行sql语句,返回ResultSet String sql = "select * from t_stu"; rs = st.executeQuery(sql); // 4. 遍历结果集 while (rs.next()) { String name = rs.getString("name"); int age = rs.getInt("age"); System.out.println(name + " " + age); } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.release(conn, st, rs); } } @Test public void testInsert(){ // 查询 Connection conn = null; Statement st = null; try { // 1. 获取链接对象 conn = JDBCUtil.getConn(); // 2. 根据链接对象,获得statement st = conn.createStatement(); //3. 执行添加 String sql = "insert into t_stu values(null , 'aobama' , 59)"; //影响的行数, ,若是大于0 代表操做成功。 不然失败 int result = st.executeUpdate(sql); if(result >0 ){ System.out.println("添加成功"); }else{ System.out.println("添加失败"); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, st); } } @Test public void testDelete(){ // 查询 Connection conn = null; Statement st = null; try { // 1. 获取链接对象 conn = JDBCUtil.getConn(); // 2. 根据链接对象,获得statement st = conn.createStatement(); //3. 执行添加 String sql = "delete from t_stu where name='aobama'"; //影响的行数, ,若是大于0 代表操做成功。 不然失败 int result = st.executeUpdate(sql); if(result >0 ){ System.out.println("删除成功"); }else{ System.out.println("删除失败"); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, st); } } @Test public void testUpdate(){ // 查询 Connection conn = null; Statement st = null; try { // 1. 获取链接对象 conn = JDBCUtil.getConn(); // 2. 根据链接对象,获得statement st = conn.createStatement(); //3. 执行添加 String sql = "update t_stu set age = 26 where name ='qyq'"; //影响的行数, ,若是大于0 代表操做成功。 不然失败 int result = st.executeUpdate(sql); if(result >0 ){ System.out.println("更新成功"); }else{ System.out.println("更新失败"); } } catch (Exception e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, st); } } }
package com.itheima.dao; /** * 定义操做数据库的方法 */ public interface UserDao { //update t_user set name=? where id = ? /** * 根据id去更新具体的用户名 * @param id * @param name */ void update(int id , String name); void delete(int id); /** * 执行添加 * @param userName * @param password */ void insert(String userName , String password); /** * 查询全部 */ void findAll(); /** * 登陆方法 * @param username * @param password */ void login(String username , String password); }
package com.itheima.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.itheima.dao.UserDao; import com.itheima.uitl.JDBCUtil; public class UserDaoImpl implements UserDao{ @Override public void findAll() { Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 获取链接对象 conn = JDBCUtil.getConn(); //2. 建立statement对象 st = conn.createStatement(); String sql = "select * from t_user"; rs = st.executeQuery(sql); while(rs.next()){ String userName = rs.getString("username"); String password = rs.getString("password"); System.out.println(userName+"="+password); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } } /*@Override public void login(String username, String password) { Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 获取链接对象 conn = JDBCUtil.getConn(); //2. 建立statement对象 st = conn.createStatement(); // SELECT * FROM t_user WHERE username='admin' AND PASSWORD='10086' String sql = "select * from t_user where username='"+ username +"' and password='"+ or +"'"; rs = st.executeQuery(sql); if(rs.next()){ System.out.println("登陆成功"); }else{ System.out.println("登陆失败"); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } }*/ @Override public void login(String username, String password) { Connection conn = null; Statement st = null; ResultSet rs = null; try { //1. 获取链接对象 conn = JDBCUtil.getConn(); //2. 建立statement对象 String sql = "select * from t_user where username=? and password=?"; //预先对sql语句执行语法的校验, ? 对应的内容,后面无论传递什么进来,都把它当作是字符串。 or select PreparedStatement ps = conn.prepareStatement(sql); //? 对应的索引从 1 开始。 ps.setString(1, username); ps.setString(2, password); rs = ps.executeQuery(); if(rs.next()){ System.out.println("登陆成功"); }else{ System.out.println("登陆失败"); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, st, rs); } } @Override public void insert(String userName, String password) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCUtil.getConn(); String sql = "insert into t_user values(null , ? , ?)"; ps = conn.prepareStatement(sql); //给占位符赋值 从左到右数过来,1 表明第一个问号, 永远你是1开始。 ps.setString(1, userName); ps.setString(2, password); int result = ps.executeUpdate(); if(result>0){ System.out.println("添加成功"); }else{ System.out.println("添加失败"); } } catch (SQLException e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, ps); } } @Override public void delete(int id) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCUtil.getConn(); String sql = "delete from t_user where id = ?"; ps = conn.prepareStatement(sql); //给占位符赋值 从左到右数过来,1 表明第一个问号, 永远你是1开始。 ps.setInt(1, id); int result = ps.executeUpdate(); if(result>0){ System.out.println("删除成功"); }else{ System.out.println("删除失败"); } } catch (SQLException e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, ps); } } @Override public void update(int id, String name) { Connection conn = null; PreparedStatement ps = null; try { conn = JDBCUtil.getConn(); String sql = "update t_user set username=? where id =?"; ps = conn.prepareStatement(sql); //给占位符赋值 从左到右数过来,1 表明第一个问号, 永远你是1开始。 ps.setString(1, name); ps.setInt(2, id); int result = ps.executeUpdate(); if(result>0){ System.out.println("更新成功"); }else{ System.out.println("更新失败"); } } catch (SQLException e) { e.printStackTrace(); }finally{ JDBCUtil.release(conn, ps); } } }
package com.itheima.test; import org.junit.Test; import com.itheima.dao.UserDao; import com.itheima.dao.impl.UserDaoImpl; public class TestUserDaoImpl { @Test public void testInsert(){ UserDao dao = new UserDaoImpl(); dao.insert("aobama", "911"); } @Test public void testUpdate(){ UserDao dao = new UserDaoImpl(); dao.update(2, "itheima"); } @Test public void testDelete(){ UserDao dao = new UserDaoImpl(); dao.delete(30); } @Test public void testFindAll(){ //面向父类编程 接口编程 UserDao dao = new UserDaoImpl(); //体现多态的特征 // UserDaoImpl dao = new UserDaoImpl(); dao.findAll(); } // "10087 "+" or 1=1" === “10087 or 1=1” @Test public void testLogin(){ UserDao dao = new UserDaoImpl(); dao.login("admin", "100234khsdf88' or '1=1"); // dao.login("admin", "10087 "+" or 1=1"); // select * from t_user where username='admin' and password='100234khsdf88'or '1=1' // SELECT * FROM t_user WHERE username='admin' AND PASSWORD='10087' or '1=1' } }
package com.itheima.uitl; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一个属性配置对象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用类加载器,去读取src底下的资源文件。 后面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //导入输入流。 properties.load(is); //读取属性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 获取链接对象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 创建链接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class MyServlet */ @WebServlet("/MyServlet") public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public MyServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 类加载器: classes 目录 getClass().getClassLoader().getResourceAsStream("aa.txt"); // servletCotnext 取东西 D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test // getServletContext().getResourceAsStream(""); // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\WEB-INF/classes/aa.txt // String path = getServletContext().getRealPath("WEB-INF/classes/aa.txt"); // System.out.println("path="+path); // -------------------------------------------------- // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\ // String path = getServletContext().getRealPath("aa\aa.txt"); // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\WEB-INF/classes // D:\tomcat\apache-tomcat-7.0.52\wtpwebapps\Test\aa\aa.txt getClass().getClassLoader().getResourceAsStream(""); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
package com.itheima.jdbc.util; import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 建立一个属性配置对象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用类加载器,去读取src底下的资源文件。 后面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //导入输入流。 properties.load(is); //读取属性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 获取链接对象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 创建链接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st ){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
package com.itheima.test; import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.junit.Test; import com.itheima.jdbc.util.JDBCUtil; public class TestDemo implements Serializable{ @Test public void test02(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConn(); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); //扣钱, 扣ID为1 的100块钱 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); //int a = 10 /0 ; String s = null; s.length(); //加钱, 给ID为2 加100块钱 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { JDBCUtil.release(conn, ps, rs); } } @Test public void testTransaction(){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConn(); //链接,事务默认就是自动提交的。 关闭自动提交。 conn.setAutoCommit(false); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); //扣钱, 扣ID为1 的100块钱 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); int a = 10 /0 ; //加钱, 给ID为2 加100块钱 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); //成功: 提交事务。 conn.commit(); } catch (SQLException e) { try { //事变: 回滚事务 conn.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } e.printStackTrace(); }finally { JDBCUtil.release(conn, ps, rs); } } }
package com.itheima.test; public class MainTest { public static void main(String[] args) { /*Waiter waiter = new Waitress(); waiter.service();*/ WaitressWrap waitressWrap = new WaitressWrap(new Waitress()); waitressWrap.service(); } }
package com.itheima.test; public interface UserDao { void insert(); void login(String username , String password ); // .... }
package com.itheima.test; public interface Waiter { void service(); }
package com.itheima.test; public class Waitress implements Waiter { @Override public void service() { System.out.println("在服务..."); } }
package com.itheima.test; public class WaitressWrap implements Waiter { Waiter watier = null; public WaitressWrap(Waiter watier){ this.watier = watier; } @Override public void service() { System.out.println("微笑:::"); watier.service(); } }