本文共 30338 字,大约阅读时间需要 101 分钟。
1、数据的持久化:
持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用
2、JDBC的理解:
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API)
简单理解为: JDBC,是SUN公司提供的一套接口,使用此接口可以实现对具体数据库的操作(获取连接、关闭连接、DML、DDL、TCL)
3、图示理解:
好处:
4、数据库的驱动
数据库厂商针对于JDBC这套接口,提供的具体实现类的集合
类似于↓
5、面向接口编程的思想:
JDBC是sun公司提供一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。
不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。 ————面向接口编程
方式一、方式二、方式三、方式四:作为过程迭代存在,了解即可。
方式五:最终版
//获取数据库的连接public static Connection getConncetion() throws Exception { //1.读取配置文件的4个基本信息 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"); Properties pros = new Properties(); pros.load(is); String user = pros.getProperty("user"); String password = pros.getProperty("password"); String url = pros.getProperty("url"); String driver = pros.getProperty("driver"); //2.加载driver Class.forName(driver); //3.获取连接 Connection conn = DriverManager.getConnection(url, user, password); // System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@68fb2c38 return conn;}
其中,配置文件【jdbc.properties】: 此配置文件声明在工程的src下
user=rootpassword=00000url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=truedriver=com.mysql.jdbc.Driver
/** * 操作数据库的工具类 * @author 阿昌 * @create 2020-11-21 13:40 */public class JDBCUtil { //获取数据库的连接 public static Connection getConncetion() throws Exception { //1.读取配置文件的4个基本信息 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"); Properties pros = new Properties(); pros.load(is); String user = pros.getProperty("user"); String password = pros.getProperty("password"); String url = pros.getProperty("url"); String driver = pros.getProperty("driver"); //2.加载driver Class.forName(driver); //3.获取连接 Connection conn = DriverManager.getConnection(url, user, password);// System.out.println(conn);//com.mysql.jdbc.JDBC4Connection@68fb2c38 return conn; } //关闭连接和Statement的操作 public static void closeResource(Connection conn, PreparedStatement ps){ try { if (conn != null){ conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } try { if (ps !=null){ ps.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } //关闭资源操作,方法重载 public static void closeResource(Connection conn, PreparedStatement ps, ResultSet resultSet){ try { if (conn != null){ conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } try { if (ps !=null){ ps.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } try { if (resultSet !=null){ resultSet.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } /* 使用dbutils.jar提供的DbUtils工具类实现资源的关闭 */ public static void closeResource1(Connection conn, PreparedStatement ps, ResultSet resultSet){ // try { // DbUtils.close(conn);// } catch (SQLException throwables) { // throwables.printStackTrace();// }//// try { // DbUtils.close(ps);// } catch (SQLException throwables) { // throwables.printStackTrace();// }//// try { // DbUtils.close(resultSet);// } catch (SQLException throwables) { // throwables.printStackTrace();// } DbUtils.closeQuietly(conn); DbUtils.closeQuietly(ps); DbUtils.closeQuietly(resultSet); }}
不需要细看(了解即可)// 使用Statement实现对数据表的查询操作 publicT get(String sql, Class clazz) { T t = null; Connection conn = null; Statement st = null; ResultSet rs = null; try { // 1.加载配置文件 InputStream is = StatementTest.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties pros = new Properties(); pros.load(is); // 2.读取配置信息 String user = pros.getProperty("user"); String password = pros.getProperty("password"); String url = pros.getProperty("url"); String driverClass = pros.getProperty("driverClass"); // 3.加载驱动 Class.forName(driverClass); // 4.获取连接 conn = DriverManager.getConnection(url, user, password); st = conn.createStatement(); rs = st.executeQuery(sql); // 获取结果集的元数据 ResultSetMetaData rsmd = rs.getMetaData(); // 获取结果集的列数 int columnCount = rsmd.getColumnCount(); if (rs.next()) { t = clazz.newInstance(); for (int i = 0; i < columnCount; i++) { // //1. 获取列的名称 // String columnName = rsmd.getColumnName(i+1); // 1. 获取列的别名 String columnName = rsmd.getColumnLabel(i + 1); // 2. 根据列名获取对应数据表中的数据 Object columnVal = rs.getObject(columnName); // 3. 将数据表中得到的数据,封装进对象 Field field = clazz.getDeclaredField(columnName); field.setAccessible(true); field.set(t, columnVal); } return t; } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭资源 if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (st != null) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return null; }
Scanner scan = new Scanner(System.in);String username = scan.next();...String sql = "insert into customers(name,email,birth)values('"+ name +"','" +email+ "','"+ birth +"')"
SQL 注入问题:
是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user=‘a’ OR 1 = ’ AND password = ’ OR ‘1’ = ‘1’) ,从而利用系统的 SQL 引擎完成恶意行为的做法。
SQL注入:
SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1'
其他问题:
1、Statement没办法操作Blob类型变量
2、Statement实现批量插入操作,效率低
1、PreparedStatement的理解
①PreparedStatement是Statement的子接口
②PreparedStatement预编译SQL语句
③可以解决Statement的SQL注入问题与拼串问题
2、使用PreparedStatement实现通用的增、删、改的方法: —Version 1.0
//通用的增删改操作public void update(String sql,Object ...args) throws Exception { //sql中占位符的个数与可变形参的长度相同 Connection conn = null; PreparedStatement ps = null; try { //1.获取数据库连接 conn = JDBCUtil.getConncetion(); //2.预编译sql语句,返回PreparedStatement的实例 ?:占位符 ps = conn.prepareStatement(sql); //3.填充占位符 for (int i=0;i
3、使用PreparedStatement实现通用的查询操作
//针对不同的表的通用的查询操作,返回表中的一条记录publicT getInstance(Class clazz,String sql,Object ...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConncetion(); ps = conn.prepareStatement(sql); for (int i=0;i
//针对不同的表的通用的查询操作,返回表中的多条记录构成的集合publicList getForList(Class clazz, String sql, Object ...args){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConncetion(); ps = conn.prepareStatement(sql); for (int i=0;i arrayList = new ArrayList<>(); while (rs.next()){ T t = clazz.newInstance(); //处理结果集一行数据中的每一个列:给t对象指定的属性赋值 for (int i=0;i
【总结】
两种思想:
1、面向接口编程思想:
面向SUN定义的接口编程,跟具体的数据库厂商没有关系
**2、ORM编程思想(object relational mapping)**对象关系映射
一个数据表对应一个java类 表中的一条记录对应java类的一个对象 表中的一个字段对应java类的一个属性
两种技术:
1、使用结果集的元数据: ResultSetMetaData >getColumnCount(): 获取列数 >getColumnLabel(): 获取列的别名 >说明: 如果sql中没有给字段起别名,getColumnLabel()仍然获取的是列名2、反射的使用 ①创建对应运行时类的对象 ②在运行时动态的调用指定的运行时类的属性、方法
查询的图示:
PreparedStatement可以操作Blob类型变量。
写入操作的方法: setBlob(int index,InputStream is);
读取操作的方法:
Blob blob = getBlob(int index);//或者填写别名
InputStream is = blob.getBinaryStream();
具体的insert:
//向Customers数据表中插入Blob类型字段@Testpublic void testInsert() throws Exception { Connection conncetion = JDBCUtil.getConncetion(); String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)"; PreparedStatement ps = conncetion.prepareStatement(sql); ps.setObject(1,"阿昌"); ps.setObject(2,"achang@qq.com"); ps.setObject(3,"1999-03-09"); FileInputStream fis = new FileInputStream(new File("45.jpg")); ps.setBlob(4,fis); ps.execute(); fis.close(); JDBCUtil.closeResource(conncetion,ps);}
具体的query:
//查询数据表Customers中Blob类型字段@Testpublic void testQuery() { Connection conn = null; PreparedStatement ps = null; InputStream is =null; FileOutputStream fos=null; try { conn = JDBCUtil.getConncetion(); String sql = "select id,name,email,birth,photo from customers where id = ?"; ps = conn.prepareStatement(sql); ps.setObject(1,20); ResultSet rs = ps.executeQuery(); if (rs.next()){ //方式一:getXxx(columnIndex) // int id = rs.getInt(1); // String name = rs.getString(2); // String email = rs.getString(3); // Date date = rs.getDate(4); // //方式二:getXxx(columnLabel) int id = rs.getInt("id"); String name = rs.getString("name"); String email = rs.getString("email"); Date birth = rs.getDate("birth"); Customer customer = new Customer(id, name, email, birth); System.out.println(customer); //将Blob类型的字段下载下来,以文件方式保存在本地 Blob photo = rs.getBlob("photo"); is = photo.getBinaryStream();//读取blob文件的流 fos = new FileOutputStream("阿昌.jpg");//输出下载的目标地址的流 byte[] buffer = new byte[1024]; int len; while ((len=is.read(buffer)) !=-1){ fos.write(buffer,0,len); } } } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,ps); try { if (fos!=null){ fos.close(); } if (is !=null){ is.close(); } } catch (IOException e) { e.printStackTrace(); } }}
注意:
测试使用PreparedStatement实现批量操作:
层次一:使用Statement实现
Connction conn = JDBCUtil.getConnction();Statement st = conn.createStatement();for(int i=1;i<=20000);i++){ String sql = "insert into goods(name)values('name_"+ i +"')" st.execute(sql);}
层次二:使用PreparedStatement实现替换Statement
@Testpublic void testInsert1() { Connection conn = null; PreparedStatement ps = null; try { long startTimes = System.currentTimeMillis(); conn = JDBCUtil.getConncetion(); String sql = "insert into goods(name)values(?)"; ps = conn.prepareStatement(sql); for (int i = 1;i<=20000;i++){ ps.setObject(1,"name_" + i); ps.execute(); } long endTimes = System.currentTimeMillis(); System.out.println("花费的时间为: "+(endTimes-startTimes));//20000条---601234 } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,ps); }}
层次三:使用Batch
1、addBatch()、executeBatch()、ClearBatch()
2、mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。 ?rewriteBatchedStatements=true 写在配置文件的url后面 3、使用更新的mysql 驱动:mysql-connector-java-5.1.37-bin.jar
@Testpublic void testInsert2() { Connection conn = null; PreparedStatement ps = null; try { long startTimes = System.currentTimeMillis(); conn = JDBCUtil.getConncetion(); String sql = "insert into goods(name)values(?)"; ps = conn.prepareStatement(sql); for (int i = 1;i<=1000000;i++){ ps.setObject(1,"name_" + i); //1."攒"sql ps.addBatch(); if (i % 500 ==0){ //2.执行batch ps.executeBatch(); //3.清空batch ps.clearBatch(); } } long endTimes = System.currentTimeMillis(); System.out.println("花费的时间为: "+(endTimes-startTimes));//20000条---1293,1000000条---44166 } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,ps); }}
**最终版的代码体现:**层次四:设置连接不运行自动提交数据
//批量插入的方式四: 设置连接不运行自动提交数据@Testpublic void testInsert3() { Connection conn = null; PreparedStatement ps = null; try { long startTimes = System.currentTimeMillis(); conn = JDBCUtil.getConncetion(); //设置不运行自动提交数据 conn.setAutoCommit(false); String sql = "insert into goods(name)values(?)"; ps = conn.prepareStatement(sql); for (int i = 1;i<=1000000;i++){ ps.setObject(1,"name_" + i); //1."攒"sql ps.addBatch(); if (i % 500 ==0){ //2.执行batch ps.executeBatch(); //3.清空batch ps.clearBatch(); } } //设置自动提交数据 conn.commit(); long endTimes = System.currentTimeMillis(); System.out.println("花费的时间为: "+(endTimes-startTimes));//1000000条---8437 } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,ps); }}
总结: PreparedStatement与Statement的异同【面试题】
①指出二者的关系? 子接口 与 接口的关系
②开发中,PreparedStatement替换Statement
③PreparedStatement是预编译SQL语句,编译语句后,会被数据库缓存下来,不需要每次都编译
Statement每次都需要再编译,就慢了
1、PreparedStatement能最大可能提高性能
2、防止SQL注入问题
3、批量插入数据性能高
4、可操作Blob类型变量
1.事务:
一组逻辑操作单元,使数据从一种状态变到另一种状态 > 一组逻辑操作: 一个或多个DML操作
2.事务处理的原则:
保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务**回滚(rollback)**到最初状态。
说明:
1.数据一旦提交,就不可回滚1.哪些操作会导致数据的自动提交 >DDL操作一旦执行,都会自动提交 >set_autocommit=false的方式对DDL操作失效 >DML默认情况下,一旦执行,会自动提交 >我们可以通过set_autocommit=false的方式取消DML操作的自动提交 >默认在关闭连接时,会自动提交数据
3.代码的体现:
@Test public void testUpdateWithTransaction() { Connection conn = null; try { conn = com.achang2.util.JDBCUtil.getConncetion(); //1、设置取消数据的自动提交功能 conn.setAutoCommit(false); String sql1 = "update user_table set balance = balance - 100 where user = ?"; update(conn,sql1, "AA"); //模拟网络异常 //System.out.println(10/0); String sql2 = "update user_table set balance = balance + 100 where user = ?"; update(conn,sql2, "BB"); System.out.println("转账成功"); //2、提交数据 conn.commit(); } catch (Exception e) { e.printStackTrace(); try { //3、回滚数据 conn.rollback(); } catch (SQLException throwables) { throwables.printStackTrace(); } } finally { try { //修改其为自动提交数据 //主要针对于使用数据库连接池时的使用 conn.setAutoCommit(true); } catch (SQLException throwables) { throwables.printStackTrace(); } com.achang2.util.JDBCUtil.closeResource(conn,null); }
4.考虑到事务以后,实现的通用增删改操作: Version2.0
//通用的增删改操作 --- Version2.0(考虑数据库事务)public int update(Connection conn,String sql,Object ...args) throws Exception { //sql中占位符的个数与可变形参的长度相同 PreparedStatement ps = null; try { //1.预编译sql语句,返回PreparedStatement的实例 ?:占位符 ps = conn.prepareStatement(sql); //2.填充占位符 for (int i=0;i
考虑到事务以后,实现的通用查询操作: Version2.0
//通用的查询操作,用于返回数据表中的一条记录(Version2.0: 考虑上事务)publicT getInstance(Connection conn,Class clazz,String sql,Object ...args){ PreparedStatement ps = null; ResultSet rs = null; try { conn = JDBCUtil.getConncetion(); ps = conn.prepareStatement(sql); for (int i=0;i
四大属性: ACID
原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。数据操作过程中可能出现的为:(针对隔离性)
数据库的四种隔离级别:(一致性和并发性: 一致性越好,并发性越差)
Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE。 Oracle 默认的事务隔离级别为: READ COMMITED 。
Mysql 支持 4 种事务隔离级别。Mysql 默认的事务隔离级别为: REPEATABLE READ。
如何查看并设置隔离级别:
每启动一个 mysql 程序, 就会获得一个单独的数据库连接. 每个数据库连接都有一个全局变量 @@tx_isolation, 表示当前的事务隔离级别。
查看当前的隔离级别:
SELECT @@tx_isolation;
设置当前 mySQL 连接的隔离级别:
set transaction isolation level read committed;
设置数据库系统的全局的隔离级别:
set global transaction isolation level read committed;
补充操作:
创建mysql数据库用户:
create user tom identified by 'abc123';
授予权限
#授予通过网络方式登录的tom用户,对所有库所有表的全部权限,密码设为abc123.grant all privileges on *.* to tom@'%' identified by 'abc123'; #给tom用户使用本地命令行方式,授予atguigudb这个库下的所有表的插删改查的权限。grant select,insert,delete,update on atguigudb.* to tom@localhost identified by 'abc123';
DAO: date(base) access Object 数据(库)访问对象
【BaseDAO.java】
/** * 封装了针对数据表的通用操作 * DAO: data(base) access object * @author 阿昌 * @create 2020-11-23 19:02 */public abstract class BaseDAO { private QueryRunner runner = new QueryRunner(); //通用的增删改操作 --- Version2.0(考虑数据库事务) public int update(Connection conn, String sql, Object ...args) { //sql中占位符的个数与可变形参的长度相同 int count = 0; try { count = runner.update(conn, sql, args); } catch (SQLException throwables) { throwables.printStackTrace(); } return count; } //通用的查询操作,用于返回数据表中的一条记录(Version2.0: 考虑上事务) publicT getInstance(Connection conn,Class clazz,String sql,Object ...args){ T t = null; try { t = runner.query(conn, sql, new BeanHandler (clazz), args); } catch (SQLException throwables) { throwables.printStackTrace(); } return t; } //通用的查询操作,用于返回数据表中的多条记录构成的集合(Version2.0: 考虑上事务) public List getForList(Connection conn,Class clazz, String sql, Object ...args){ List list =null; try { list = runner.query(conn, sql, new BeanListHandler<>(clazz), args); } catch (SQLException throwables) { throwables.printStackTrace(); } return list; } //用于查询特殊值的通用方法 public Object getValue(Connection conn,String sql,Object...args) { Object count = null; try { count = runner.query(conn, sql, new ScalarHandler(), args); } catch (SQLException throwables) { throwables.printStackTrace(); } return count; }}
/** * 此接口用来规范针对于Customers表的常用操作 * @author 阿昌 * @create 2020-11-23 19:22 */public interface CustomerDAO { //将cust对象添加到数据库中 void insert(Connection conn,com.achang2.bean.Customer cust) throws Exception; //根据指定id,删除表中的一条记录 void deleteById(Connection conn,int id) throws Exception; //针对于内存中的cust对象,去修改数据表中的记录 void updateById(Connection conn,com.achang2.bean.Customer cust) throws Exception; //根据指定id查询对应的Customer对象 Customer getById(Connection conn,int id); //查询表中的所有记录,构成集合 ListgetAll(Connection conn); //返回数据表中数据的条目数 Long getCount(Connection conn); //返回数据表中最大的生日 Date getMaxBirth(Connection conn);}
/** * @author 阿昌 * @create 2020-11-23 19:36 */public class CustomerDAOImpl extends BaseDAO implements CustomerDAO { @Override public void insert(Connection conn, com.achang2.bean.Customer cust) throws Exception { String sql = "insert into customers(name,email,birth)values(?,?,?)"; update(conn,sql,cust.getName(),cust.getEmail(),cust.getBirth()); } @Override public void deleteById(Connection conn, int id) throws Exception { String sql = "delete from customers where id =?"; update(conn,sql,id); } @Override public void updateById(Connection conn, com.achang2.bean.Customer cust) throws Exception { String sql = "update customers set name = ?,email = ?,birth = ? where id= ?"; update(conn,sql,cust.getName(),cust.getEmail(),cust.getBirth(),cust.getId()); } @Override public Customer getById(Connection conn, int id) { String sql = "select id,name,email,birth from customers where id = ?"; Customer customer = getInstance(conn, Customer.class, sql, id); return customer; } @Override public List getAll(Connection conn) { String sql = "select id,name,email,birth from customers"; Listlist = getForList(conn, com.achang2.bean.Customer.class,sql); return list; } @Override public Long getCount(Connection conn) { String sql = "select count(*) from customers"; return (Long) getValue(conn, sql); } @Override public Date getMaxBirth(Connection conn) { String sql = "select max(birth) from customers"; return (Date) getValue(conn,sql); }}
1、获取数据库连接
Connection conn = JDBCUtils.getConnection();//方式一: 手动获取连接 方式二:数据库连接池
conn.setAutoCommit(false); //体现事务
2、如下的多个DML操作,作为一个事务出现:
操作①: 需要使用通用的增删改查操作 //通用的增删改查操作如何实现?
操作②: 需要使用通用的增删改查操作 //方式一: 手动使用PreparedStatement实现
操作③: 需要使用通用的增删改查操作 //方式二: 使用dbutil.jar中QueryRunner类
conn.commit();
3、如果出现异常,则:
conn.rollback()
4、关闭资源
JDBCUtils.closeResource(…,…,…,); //方式一: 手动关闭资源 方式二:DbUtils类的关闭方法
1.传统连接的问题:
2.如何解决传统开发中的数据库连接问题:
3.使用数据库连接池的好处:
① 资源重用
由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。
② 更快的系统反应速度
数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间
③新的资源分配手段
对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源
④统一的连接管理,避免数据库连接泄漏
在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露
自己的话总结:
①提高了程序的相应速度(减少了创建连接相应的时间)
②降低资源的消耗,提供资源利用率(可以重复使用已经提供好的连接)
③便于连接的管理
4.实现的方法:
导入jar包:
测试连接的代码:
//使用C3P0的数据库连接池技术//数据库连接池只需要提供一个即可private static ComboPooledDataSource cpds = new ComboPooledDataSource("helloC3p0");public static Connection getConnection1() throws Exception { Connection conn = cpds.getConnection(); return conn;}
其中,配置文件定义在src下。名为:c3p0-config.xml
com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/test root 00000 5 100 10 100 50 2
导入jar包:
测试连接的代码:
//使用DBCP的数据库连接池技术private static DataSource source;static { Properties pros = new Properties(); try { //创建流 FileInputStream is = new FileInputStream("src/dbcp.properties"); pros.load(is); //创建一个DBCP数据库连接池 source = BasicDataSourceFactory.createDataSource(pros); } catch (Exception e) { e.printStackTrace(); }}public static Connection getConnection2() throws Exception { Connection conn = source.getConnection(); return conn;}
其中,配置文件定义在src下。名为dbcp.properties
driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/testusername=rootpassword=00000initialSize=10...
导入jar包:
测试连接的代码:
//Druid数据库连接池技术private static DataSource source1;static { try { Properties pros = new Properties(); InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties"); pros.load(is); source1 = DruidDataSourceFactory.createDataSource(pros); } catch (Exception e) { e.printStackTrace(); }}public static Connection getConnection3() throws Exception { //创建Druid数据库连接池 Connection conn = source1.getConnection(); return conn;}
其中,配置文件定义在src下。名为druid.properties
driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/testusername=rootpassword=00000initialSize=5...
导入jar包:
使用现成的jar中的QueryRunner测试增删改操作:
//测试插入操作@Testpublic void testInsert() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtil.getConnection3(); String sql = "insert into customers(name,email,birth)values(?,?,?)"; int insertCount = runner.update(conn, sql, "韩信", "Hanxin@qq.com", new Date(5635515L)); System.out.println("添加了 "+insertCount+" 条记录"); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,null); }}
使用现成的jar中的QueryRunner测试查询操作:
//测试查询操作 /* BeanHandler: 是ResultSetHandler接口的实现类,用于封装表中的一条记录 */ @Test public void testQuery1() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtil.getConnection3(); String sql = "select id,name,email,birth from customers where id = ?"; BeanHandlerhandler = new BeanHandler (Customer.class); Customer cust = runner.query(conn, sql, handler, 20); System.out.println(cust); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,null); } } /* BeanListHandler: 是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合 */ @Test public void testQuery2() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtil.getConnection3(); String sql = "select id,name,email,birth from customers where id < ?"; BeanListHandler handler = new BeanListHandler (Customer.class); List list = runner.query(conn, sql, handler, 20); list.forEach(System.out::println); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,null); } } /*MapHandler: 是ResultSetHandler接口的实现类,对应表中的 一条 记录。 将字段及相应字段的值作为map中的Key和Value */ @Test public void testQuery3() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtil.getConnection3(); String sql = "select id,name,email,birth from customers where id = ?"; MapHandler handler = new MapHandler(); Map map = runner.query(conn, sql, handler, 20); System.out.println(map); } catch (Exception e) { e.printStackTrace(); } finally { JDBCUtil.closeResource(conn,null); } } /* MapListHandler: 是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合 将字段及相应字段的值作为map中的Key和Value。将这些map添加到List中 */ @Test public void testQuery4() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtil.getConnection3(); String sql = "select id,name,email,birth from customers where id < ?"; MapListHandler handler = new MapListHandler(); List
使用dbutils.jar包中DbUtils工具类实现连接等资源的关闭:
/* 使用dbutils.jar提供的DbUtils工具类实现资源的关闭 */public static void closeResource1(Connection conn, PreparedStatement ps, ResultSet resultSet){ // try { // DbUtils.close(conn); // } catch (SQLException throwables) { // throwables.printStackTrace(); // } // // try { // DbUtils.close(ps); // } catch (SQLException throwables) { // throwables.printStackTrace(); // } // // try { // DbUtils.close(resultSet); // } catch (SQLException throwables) { // throwables.printStackTrace(); // } DbUtils.closeQuietly(conn); DbUtils.closeQuietly(ps); DbUtils.closeQuietly(resultSet);}
感谢尚硅谷
学习视频 https://www.bilibili.com/video/BV1eJ411c7rf
转载地址:http://rboq.baihongyu.com/