在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一、JDBC的概述 1.JDBC为访问不同的数据薛是供了统一的接口,为使用者屏蔽了细节问题。
二。JDBC带来的好处 java程序可以直接对数据库进行调用,但是没有很好的移植性(对用于不同的数据库),所以不推荐 JDBC带来的好处:JDBC是java提供一套用于数据库操作的接口API,Java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。
JDBC API:JDBC API 是一系列的接口,它统一和规范了应用程序与数据库的连接,执行SQL语句,并得到返回结果等各类操作;
JDBC程序编写步骤 1、注册驱动 --- 加载Driver类 2、获取连接 --- 得到Connection 3、执行增删改查 --- 发送Sql给mysql执行 4、释放资源 --- 关闭相关连接 获取数据库连接的5种方式: 方式1:使用(com.mysql.jdbc.Driver)com.mysql.cj.jdbc.Driver,属于静态加载,灵活性差,依赖性强 方式2:使用反射机制,属于静态加载
方式3:使用DriverManager替代driver进行统一管理
方式4:使用Class.forName自动完成注册驱动,简化代码 这种方式连接是使用得最多的(推荐使用)
在底层会完成注册:
提示: (1)mysql驱动5.1.6可以无需Class.forName(“com.mysql.jdbc.Driver”); (2)从jdk1.5以后使用了jdbc4,不再需要显示调用class.forName()注册驱动而是自动调用驱动jar包下META-INF\servicesljava .sql.Driver文本中的类名称去注册 (3)建议加上Class.forName(“com.mysql.jdbc.driver”),能够更加明确的感受到程序流程,利于掌握; 方式5:利用properties文件配置数据库需要的相关的配置 更加的灵活,可以直接通过properties配置文件修改数据库连接相关的数据
对方式5的实例: //properties配置文件 driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/test_db?useSSL=false&characterEncoding=utf8&serverTimezone=UTC user=root password=123456 //连接数据库的相关操作 import java.io.*; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class jdbc02 { public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException { //创建一个properties对象 Properties properties = new Properties(); //加载和获取创建的properties的相关数据 properties.load(new FileInputStream("src\\db.properties")); String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String sql = "insert into actor values (null,'王五','男','1975-11-23','110')"; //driver驱动,也可以不加,但是加上更容易读懂流程 Class.forName(driver); //连接和执行操作 Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); statement.executeUpdate(sql); //关闭连接 System.out.println("连接"+connection); statement.close(); connection.close(); } } 三、RestSet【结果集】 基本介绍: 1.表示数据库结果集的数据表,通常通过执行查询数据库的语句生成 3. next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回 简单测试:
四、Statement: 基本介绍: 1.Statement对象用于执行静态SQL语句并返回其生成的结果的对象 Statement【存在SQL注入】 3. Statement对象执行SQL语句,存在SQL注入风险 4.SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库。 5.要防范SQL注入,只要用 PreparedStatement(从Statement扩展而来)取 import java.io.*; import java.sql.*; import java.util.Properties; public class jdbc02 { public static void main(String[] args) throws ClassNotFoundException, IOException, SQLException { //创建一个properties对象 Properties properties = new Properties(); //加载和获取创建的properties的相关数据 properties.load(new FileInputStream("src\\db.properties")); String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String sql = "insert into actor values (null,'三毛','男','1975-11-23','110')"; String sql1 = "select id,name from actor"; //driver驱动,也可以不加,但是加上更容易读懂流程 Class.forName(driver); //连接和执行操作 Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); // statement.executeUpdate(sql); // String sql1 = "select id,name from actor"; ResultSet resultSet = statement.executeQuery(sql1); while (resultSet.next()) { int i = resultSet.getInt(1); String string1 = resultSet.getString(2); System.out.println(i+"=="+string1); } //关闭连接 resultSet.close(); System.out.println("连接"+connection); statement.close(); connection.close(); } }
PrepareStatement: 1. PreparedStatement 执行的SQL语句中的参数用问号(?)来表示,调用 预处理的好处: 1.不再使用+拼接sql语句,减少语法错误 2.有效的解决了sql注入问题! 对preparestatement的测试代码,配置文件还是上面的配置文件 import java.io.FileInputStream; import java.io.FileNotFoundException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Properties; public class PrepareStatement { public static void main(String[] args) throws Exception { Properties properties = new Properties(); properties.load(new FileInputStream("src\\db.properties")); String drive = properties.getProperty("driver"); String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); //更新操作 // String sql = "update actor set phone = ? where name = ?"; //删除操作 // String sql = "delete from actor where name = ?"; // 添加操作 // String sql = "insert into actor values(null,?,?,?,?)"; //查询操作 String sql = "select * from actor"; Class.forName(drive); Connection connection = DriverManager.getConnection(url, user, password); PreparedStatement preparedStatement = connection.prepareStatement(sql); //更改操作 // preparedStatement.setString(1, "123456"); // preparedStatement.setString(2, "三毛"); //删除操作 // preparedStatement.setString(1, "二狗"); //添加操作 // preparedStatement.setString(1, "张三"); // preparedStatement.setString(2, "男"); // preparedStatement.setString(3, "1975-11-23 00:00:00"); // preparedStatement.setString(4,"456789"); // int i = preparedStatement.executeUpdate(); // System.out.println(i >0 ? "成功" : "失败"); //查询操作 ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println(resultSet.getString(2)); } preparedStatement.close(); connection.close(); } } 总结:
五、事务:将多行代码当做SQL事务来处理,主要流程需要的关键代码: connection.setAutoCommit(false);//取消自动提交的操作,取消之后,会在提及之后完成事务 connection.rollback();//用于回退事务 1、当需要成批插入或者更新记录时。可以采用Java的批量更新机制,这一机制允 2、JDBC的批量处理语句包括下面方法: 过程: (1)将sql语句加入到批处理包中 preparedStatement.addBatch(); (2)执行sql和清空sql //批量执行sql语句 将 SQL加入到批处理包中源码所做的事情:
六、数据库连接池 传统connection问题分析: 1.传统的JDBC数据库连接使用 DriverManager来获取,每次向数据库建立 数据库连接池基本介绍: 1.预先在缓冲池中放入一定数量的连接,,当需
数据库连接池示意图: 数据库连接池种类: 1.JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource 3.DBCP数据库连接池,速度相对c3p0较快,但不稳定 5.BoneCP数据库连接池,速度快
测试:C3P0连接池的连接(需要导入第三方库:c3p0的jar包) 第一个C3P0连接的配置文件还是上面的配置文件内容 第二个C3P0的连接需要有一个xml配置文件 import com.mchange.v2.c3p0.ComboPooledDataSource; import org.junit.jupiter.api.Test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class ConDatasource { public static void main(String[] args) throws Exception { Properties properties = new Properties(); properties.load(new FileInputStream("src\\db.properties")); String driver = properties.getProperty("driver"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String url = properties.getProperty("url"); //建立comboPooledDataSource管理连接池 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setDriverClass(driver); comboPooledDataSource.setJdbcUrl(url); comboPooledDataSource.setUser(user); comboPooledDataSource.setPassword(password); //设置初始化连接数和最大连接数 comboPooledDataSource.setInitialPoolSize(10); comboPooledDataSource.setMaxPoolSize(50); //这个方法就是从DataSource接口实现的 Connection connection = comboPooledDataSource.getConnection(); System.out.println("1连接成功"); connection.close(); } @Test public void ConDatasource02() throws SQLException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("test_C3P0"); long start = System.currentTimeMillis(); System.out.println("测试连接5000次需要的时间"); for (int i = 0; i < 5000; i++) { Connection connection = comboPooledDataSource.getConnection(); // System.out.println("2连接成功"); connection.close(); } long end = System.currentTimeMillis(); System.out.println("花费时长:"+(end-start)); } } //第二种方式的xml文件 <c3p0-config> <named-config name="test_C3P0"> <!-- 驱动类 --> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <!-- url--> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test_db?useSSL=false&characterEncoding=utf8&serverTimezone=UTC</property> <!-- 用户名 --> <property name="user">root</property> <!-- 密码 --> <property name="password">123456</property> <!-- 每次增长的连接数--> <property name="acquireIncrement">5</property> <!-- 初始的连接数 --> <property name="initialPoolSize">10</property> <!-- 最小连接数 --> <property name="minPoolSize">5</property> <!-- 最大连接数 --> <property name="maxPoolSize">10</property> <!-- 可连接的最多的命令对象数 --> <property name="maxStatements">5</property> <!-- 每个连接对象可连接的最多的命令对象数 --> <property name="maxStatementsPerConnection">2</property> </named-config> </c3p0-config> 测试:Druid连接池的连接(需要第三方库druid的jar包) package com.zjl.jdbc; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.sql.Connection; import java.util.Properties; public class Druidsource { public static void main(String[] args) throws Exception { Properties properties = new Properties(); properties.load(new FileInputStream("src\\druid.properties"));//如下定义的配置文件 DataSource dataSource = DruidDataSourceFactory.createDataSource(properties); long start = System.currentTimeMillis(); for (int i = 0;i < 500000;i++ ) { Connection connection = dataSource.getConnection(); connection.close(); } long end = System.currentTimeMillis(); System.out.println("Druid连接5000 次需要的时间:" + (end - start));//Druid连接500000 次需要的时间:625 } } druid.properties:放在src目录下
#key=value
注意:对于c3p0和Druid他们的close()是按照第三方库的连接方式,仅仅是将从连接池引用的数据库连接断开(放弃引用) 重新将连接放回到连接池中,和原生 的jdbc连接中的close方法断开连接不同; 用Druid创建一个连接和断开的工具类; package com.zjl.jdbc; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.FileInputStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtilsByDruid { static DataSource ds; static { Properties properties = new Properties(); try { properties.load(new FileInputStream("src\\druid.properties")); ds = DruidDataSourceFactory.createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } } //编写获取Connection的方法 public static Connection getConnection() throws SQLException { return ds.getConnection(); } public static void close(ResultSet resultSet, Statement statement, Connection connection) { try { if (resultSet != null) { resultSet.close(); } if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { //将编译异常转成运行异常抛出 throw new RuntimeException(e); } } }
七、Apache-DBUtils 1、问题引出:在使用Druid连接数据库,返回结果集之后,如果断开连接,结果集就不能够再使用。解决方法如图,将返回的结果集保存到一个泛型列表中,那么当数据库连接断开后,还是可以使用返回的结果集。
2、对Apache-DBUtils的基本介绍 1).commons-dbutils 是 Apache组织提供的一个开源 JDBC工具类库,它是对JDBC的封装, (2).使用QueryRunner类实现查询 对该DBUtils进行测试:需要对应的jar包(commons-dbutils-1.7.jar)可以去:http://commons.apache.org/下载 相应的JDBCUtilsByDruid类是上面的测试类: package com.zjl.jdbc; import com.zjl.bean.Actor; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Iterator; import java.util.List; public class TestDBUtils { public static void main(String[] args) throws Exception { String sql = "select * from `actor`"; //从Druid中获取一个连接 Connection connection = JDBCUtilsByDruid.getConnection(); //引入DBUtils的jar包,并获得一个QueryRunner对象 QueryRunner queryRunner = new QueryRunner(); //利用QueryRunner对象就可以直接查询数据库,执行SQl语句,返回结果封装到ArrayList集合中 // connection是一个连接,sql是一个执行语句 //new BeanListHandler<>(Actor.class):在将resultSet中的结果以Actor对象方式封装到ArrayList //底层使用反射机制,获取Actor类的属性,然后进行封装 //1就是给sql 语句中的?赋值,可以有多个值,因为是可变参数0bject... params // List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1); //如果要返回单个查询数据就使用BeanHandler<>(Actor.class),返回结果就会是单个对象或者为空 List<Actor> list = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class)); //在底层会得到resultSet并在query中关闭,也会在底层使用preparedStatement并关闭 // JDBCUtilsByDruid.close(null, null, connection); Iterator<Actor> iterator = list.iterator(); while (iterator.hasNext()) { Actor next = iterator.next(); System.out.println(next); } //进行更新操作 String updateSql = "update `actor` set name = ? where id = ?"; int update = queryRunner.update(connection, updateSql, "王无无", 8); System.out.println((update > 0) ? "更新成功" : "更新失败"); //进行删除操作 String delSql = "delete from `actor` where id = ?"; int update1 = queryRunner.update(connection, delSql, 10); System.out.println((update > 0) ? "删除成功" : "删除失败"); //关闭资源 JDBCUtilsByDruid.close(null, null, connection); } } 八、BasicDao--DAO和增删改查通用方法(DAO:data access object 数据访问对象) 基本说明: 1)、 DAO:data access object数据访问对象 3)、在BaiscDao的基础上,实现一张表对应一个Dao,更好的完成功能; 关系图如下:
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论