JDBC数据库连接
介绍jdbcjava数据库连接技术通俗点说在java代码中使用JDBC提供的方法可以发送字符串类型的sql语句到数据库管理软件并且获取语句执行结果进而实现数据库CRUD操作技术优势只需要学习jdbc接口规定方法即可操作所有的数据库软件项目中期需要切换数据库我们只需要更新第三方驱动jar包不需要更改代码。jdbc核心api和使用路线1.jdk下jdbc规范接口存储在java.sql和javax.sql包中的api为了项目的可移植性可维护性sun公司最初就制定了java程序连接各种数据库的统一接口规范2.各个数据库厂商提供的驱动jar包涉及具体核心类和接口DriverManger1.将第三方数据库厂商的实现驱动jar注册到程序中2.可以根据数据库连接信息获取connectionConnection1.和数据库建立的连接在连接对象上可以多次执行数据库crud动作2.可以获取statement preparestatement callablestatement对象Statement PreparedStatement CallableStatement1.具体发送sql语句到数据库管理软件的对象2.不同的发送方式稍有不同Result1.面向对象的产物抽象成数据库的查询结果表2.存储DQL查询数据库结果的对象3.需要我们进行解析获取具体的数据库数据JDBC API使用路线为什么使用全新8版本mysql-jdbc驱动支持jdk1.8版本语法变更新特性支持全新的驱动api增加自动时区选择和默认utf-8编码格式等配置核心API Statementpackage com.at; import com.mysql.cj.jdbc.Driver; import java.sql.*; public class Main { public static void main(String[] args) throws SQLException { DriverManager.registerDriver(new Driver()); /*获取连接 * * java程序要和数据库创建连接 * java程序连接数据库肯定是调用某个方法方法也需要填入连接数据库的基本信息 * * 数据库ip地址127.0.0.1 * 数据库端口号3306 * 账号 * 密码 * */ /*java.sql 接口实现类*/ Connection connection DriverManager.getConnection(jdbc:mysql://127.0.0.1:3306/studb, root, 080666); /*创建statement*/ Statement statement connection.createStatement(); String sqlselect *from students; ResultSet resultSet statement.executeQuery(sql); while (resultSet.next()){ int id resultSet.getInt(id); String name resultSet.getString(name); int password resultSet.getInt(age); System.out.println(id name password); } resultSet.close(); statement.close(); connection.close(); } }package com.at; import com.mysql.cj.jdbc.Driver; import javax.sql.DataSource; import java.sql.*; import java.util.Properties; import java.util.Scanner; public class a { public static void main(String[] args) throws SQLException, ClassNotFoundException { Scanner scanner new Scanner(System.in); String id scanner.nextLine(); String age scanner.nextLine(); /* * 问题注册两次驱动 * 解决只想触发一次驱动 * 只触发静态代码块即可 * * */ /*方案1*//* new Driver();*/ //方案2 Class.forName(com.mysql.cj.jdbc.Driver); Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/test?, root, 080666); Properties properties new Properties(); properties.put(user, root); properties.put(password, 080666); Connection connection1 DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, properties); Connection connection2 DriverManager.getConnection(jdbc:mysql://localhost:3306/test?userrootpassword080666); Statement statement connection1.createStatement(); String sql select * from students where id id and age age;; ResultSet resultSet statement.executeQuery(sql); /* * 如果想进行数据解析我们需要进行两件事情 * 1.移动游标指定获取数据行 * 2.获取指定数据行的列数据即可 * * 1.游标移动问题 * resultSet内部包含一个游标指定当前换行数据 * 默认游标指定的是第一行数据 * 我们可以用next方法向后移动一行游标 * 如果我们有多行数据我们可以使用whilenext{获取每一行的数据} * boolean next {} * true 有更多的数据并且向下移动一行 * false 没有更多的数据不一定 * * 如果next不满足我们的要求是我们的查询条件出现问题了 * * 2.获取列的数据问题获取光标指定的行的列的数据 * * resultSet.get类型String columnLabel / int columnIndex * columnLabel列名 如果有别名 写别名 * columnIndex列的下角标 从左往右 从1开始 * * while (resultSet.next()){ int id resultSet.getInt(id); String s resultSet.getString(2); int password resultSet.getInt(age); System.out.println(id s password); } */ while (resultSet.next()){ int id1 resultSet.getInt(id); String s1 resultSet.getString(name); String gender resultSet.getString(gender); /* int anInt resultSet.getInt(age);*/ String aClass resultSet.getString(class); System.out.println(id1 s1 gender aClass); } resultSet.close(); statement.close(); connection1.close(); } }问题SQL语句需要字符串拼接比较麻烦只能拼接字符串类型其他的数据类型无法处理可能发生注入攻击动态值充当了sql语句结构影响了原有的查询结果核心API preparedstatementpackage com.at; import javax.sql.DataSource; import java.sql.*; import java.util.Scanner; public class b { public static void main(String[] args) throws ClassNotFoundException, SQLException { Scanner scanner new Scanner(System.in); String username scanner.nextLine(); String password scanner.nextLine(); Class.forName(com.mysql.cj.jdbc.Driver); Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/studb?useSSLfalseserverTimezoneUTC, root, 080666); /* * statement * 1.创建Statement * 2.拼接sql语句 * 3.发送sql语句并获取返回结果 * * * preparedstatement * 1.编写sql语句结果 不包含动态值部分的语句动态值部分使用占位符替代 注意只能替代动态值 * 2.创建preparedstatement并且传入动态值 * 3.动态值 占位符 赋值 单独赋值即可 * 4.发送sql语句并获取返回结果 * */ String sqlselect * from students where id? and age?; PreparedStatement preparedStatement connection.prepareStatement(sql); preparedStatement.setObject(1,username); preparedStatement.setObject(2,password); /* * 单独占位符进行赋值 * 参数1.index 占位符的位置 从左向右 从1开始 * 参数2.object 占位符的值 可以设置任何类型的数据避免了我们拼接和类型更加丰富 * */ ResultSet resultSet preparedStatement.executeQuery(); if (resultSet.next()){ System.out.println(登录成功); } else System.out.println(登录失败); resultSet.close(); preparedStatement.close(); connection.close(); } }核心API preparedstatement CRUDpackage com.at; import org.testng.annotations.Test; import javax.sql.DataSource; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class c { Test public void insert() throws Exception { Class.forName(com.mysql.cj.jdbc.Driver); Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, root, 080666); String sqlinsert into students(id,name,gender,age,class) values (?,?,?,?,?);; PreparedStatement preparedStatement connection.prepareStatement(sql); preparedStatement.setObject(1, 1001); preparedStatement.setObject(2, 张三); preparedStatement.setObject(3, 男); preparedStatement.setObject(4, 18); preparedStatement.setObject(5, 1班); int i preparedStatement.executeUpdate(); if (i0){ System.out.println(插入成功); }else System.out.println(插入失败); preparedStatement.close(); connection.close(); } Test public void update() throws ClassNotFoundException, SQLException { Class.forName(com.mysql.cj.jdbc.Driver); Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, root, 080666); String sql update students set name?,gender?,age?,class? where id?;; PreparedStatement preparedStatement connection.prepareStatement(sql); preparedStatement.setObject(1, 李四); preparedStatement.setObject(2, 男); preparedStatement.setObject(3, 19); preparedStatement.setObject(4, 2班); preparedStatement.setObject(5, 1001); int i preparedStatement.executeUpdate(); if (i 0) { System.out.println(更新成功); } else{ System.out.println(更新失败); } preparedStatement.close(); connection.close(); } Test public void delete() throws ClassNotFoundException, SQLException { Class.forName(com.mysql.cj.jdbc.Driver); Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, root, 080666); String sql delete from students where id?;; PreparedStatement preparedStatement connection.prepareStatement(sql); preparedStatement.setObject(1, 1001); int i preparedStatement.executeUpdate(); if (i 0) { System.out.println(删除成功); } else { System.out.println(删除失败); preparedStatement.close(); connection.close(); } } Test public void select() throws ClassNotFoundException, SQLException { } }//纯手动获取 Test public void select() throws ClassNotFoundException, SQLException { Class.forName(com.mysql.cj.jdbc.Driver); Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, root, 080666); String sql select * from students;; PreparedStatement preparedStatement connection.prepareStatement(sql); ResultSet resultSet preparedStatement.executeQuery(); ListMap list new ArrayList(); while (resultSet.next()) { Map map new HashMap(); /*一行数据对应一个map*/ map.put(id, resultSet.getObject(id)); map.put(name, resultSet.getObject(name)); map.put(gender, resultSet.getObject(gender)); map.put(age, resultSet.getObject(age)); map.put(class, resultSet.getObject(class)); /*一行数据的所有列全部存到了map中*/ /*将map存储到集合中即可*/ list.add(map); } System.out.println(list); resultSet.close(); preparedStatement.close(); connection.close(); } /*自动*/ Test public void select2() throws ClassNotFoundException, SQLException { Class.forName(com.mysql.cj.jdbc.Driver); Connection connection DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, root, 080666); String sql select * from students;; PreparedStatement preparedStatement connection.prepareStatement(sql); ResultSet resultSet preparedStatement.executeQuery(); ResultSetMetaData metaData resultSet.getMetaData(); /*获取列的信息*/ /*获取当前结果集列的信息对象 也可以获取列的名称根据下角标可以获取列的数量*/ int columnCount metaData.getColumnCount(); /*有了他我们可以水平遍历列*/ ListMap list new ArrayList(); while (resultSet.next()) { Map map new HashMap(); for (int i 1; i columnCount; i) { /*自动遍历序列注意要从1开始并且小于等于总列数*/ /*获取下角标的值 resultSet有关*/ Object value resultSet.getObject(i); /*获取指定列的下角标的列的名称 resultSetMetaData*/ String columnLabel metaData.getColumnLabel(i); map.put(columnLabel, value); } list.add(map); } System.out.println(list); } }扩展 主键回显和主键值获取package com.at; import javax.sql.DataSource; import java.sql.*; public class d { public static void main(String[] args) throws Exception { Class.forName(com.mysql.cj.jdbc.Driver); Connection root DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, root, 080666); String sqlinsert into students(id,name,gender,age,class) values(?,?,?,?,?); PreparedStatement preparedStatement root.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); preparedStatement.setObject(1, 102); preparedStatement.setObject(2, 张三); preparedStatement.setObject(3, 男); preparedStatement.setObject(4, 18); preparedStatement.setObject(5, 1班); int i preparedStatement.executeUpdate(); if (i 0) { System.out.println(插入成功); ResultSet generatedKeys preparedStatement.getGeneratedKeys(); generatedKeys.next(); int anInt generatedKeys.getInt(1); System.out.println(anInt); } else { System.out.println(插入失败); } preparedStatement.close(); root.close(); } }扩展 批量插入数据优化笨办法package com.at; import javax.sql.DataSource; import java.sql.*; public class d { public static void main(String[] args) throws Exception { Class.forName(com.mysql.cj.jdbc.Driver); Connection root DriverManager.getConnection(jdbc:mysql://localhost:3306/studb, root, 080666); String sqlinsert into students(id,name,gender,age,class) values(?,?,?,?,?); PreparedStatement preparedStatement root.prepareStatement(sql); long start System.currentTimeMillis(); for (int i 1; i 10000; i) { preparedStatement.setObject(1, 102i); preparedStatement.setObject(2, 张三i); preparedStatement.setObject(3, 男i); preparedStatement.setObject(4, 18i); preparedStatement.setObject(5, 1班i); preparedStatement.executeUpdate(); } long end System.currentTimeMillis(); long l end - start; System.out.println(l); preparedStatement.close(); root.close(); } }批量插入package com.at; import javax.sql.DataSource; import java.sql.*; public class d { public static void main(String[] args) throws Exception { Class.forName(com.mysql.cj.jdbc.Driver); Connection root DriverManager.getConnection( jdbc:mysql://localhost:3306/studb?rewriteBatchedStatementstrue, root, 080666); String sql insert into students(id,name,gender,age,class) values(?,?,?,?,?); PreparedStatement preparedStatement root.prepareStatement(sql); long start System.currentTimeMillis(); for (int i 10001; i 20001; i) { preparedStatement.setObject(1,10000i); preparedStatement.setObject(2, 张三 i); preparedStatement.setObject(3, 男 i); preparedStatement.setObject(4, 18 i); preparedStatement.setObject(5, 1班 i); preparedStatement.addBatch();//不执行追加到values的后面 } /* * 总结 * 路径后面添加rewriteBatchedStatementstrue 允许批量插入 * 不是执行语句每条是批量添加addBatch() * 遍历添加完毕以后统一执行executeBatch() * */ preparedStatement.executeBatch(); long end System.currentTimeMillis(); long l end - start; System.out.println(l); preparedStatement.close(); root.close(); } }事物回滚数据库连接池的作用无连接池的缺点1.不使用数据库连接池每次都通过DriverManager获取新连接用完直接抛弃断开连接的利用率太低太浪费。2.对于数据库服务器来说压力太大了我们数据库服务器和java程序对连接数也无法控制很容易导致数据库服务器崩溃。我们希望能够管理连接我们可以建立一个连接池这个池可以容纳一定数量的连接对象一开始我们可以先替用户创建好一些连接对象等用户要拿连接对象时就直接从池中拿不用新建了这样就可以节省时间。然后用户用完之后就放回去别人可以接着用。可以提高连接的使用率当池中的现有的连接用完了那么连接池就可以向服务器申请新的连接池放到池中。直到池中的连接达到最大连接数就不能在申请新的连接了如果没有拿到连接的用户只能等待。连接池的使用package com.at; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.pool.DruidDataSourceFactory; import com.alibaba.druid.pool.DruidPooledConnection; import org.testng.annotations.Test; import javax.sql.DataSource; import java.io.IOException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; public class druid { Test public void test() throws SQLException { DruidDataSource dataSource new DruidDataSource(); dataSource.setUrl(jdbc:mysql://localhost:3306/studb?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneUTC); dataSource.setDriverClassName(com.mysql.cj.jdbc.Driver); dataSource.setUsername(root); dataSource.setPassword(080666); Connection connection dataSource.getConnection(); connection.close(); } /*通过读取外部配置文件的方法实例化druid连接池对象*/ Test public void test2() throws Exception { Properties properties new Properties(); properties.load(this.getClass().getClassLoader().getResourceAsStream(druid.properties)); DataSource dataSource DruidDataSourceFactory.createDataSource(properties); Connection connection dataSource.getConnection(); String sql select * from students where id?; PreparedStatement preparedStatement connection.prepareStatement(sql); preparedStatement.setObject(1, 10001); ResultSet resultSet preparedStatement.executeQuery(); ListMap list new ArrayList(); while (resultSet.next()) { Map mapnew HashMap(); map.put(id,resultSet.getObject(id)); map.put(name,resultSet.getObject(name)); list.add(map); } System.out.println(list); } }工具类封装分解步骤变成方法高级应用封装BaseDao封装非DQL操作