Java|JDBC (Java DataBase Connectivity )的基本使用

1.JDBC的入门级使用 这边就是说明一下jdbc是怎么使用的,以及涉及到的各个对象的注意事项。

import com.mysql.jdbc.NonRegisteringDriver; import java.sql.*; public class JdbcMain { public static void main(String[] args){ Connection connection = null; //预编译功能防止sql注入 PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { //注册驱动,注意这边必须要到入相应的jar包 //这边兄弟们肯定有疑问怎么反射一下就回加载呢? //这边用了静态类我只要加载到这个文件那么DriverManager就会自己注册 /*public class Driver extends NonRegisteringDriver implements java.sql.Driver { public Driver() throws SQLException { }static { try { DriverManager.registerDriver(new com.mysql.jdbc.Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } }*/ //jdk5之后可以不写这个反射,直接就可以使用,感兴趣可以了解一下 //mysql-connector-java-5.1.37.jar!/META-INF/services/java.sql.Driver Class.forName("com.mysql.jdbc.Driver"); //获取链接,返回的是链接对象 //1.这边重要就是链接中可以控制事务的开启关闭 //2.获取执行对象 //3.使用完成需要关闭链接,释放资源 connection = DriverManager.getConnection("jdbc:mysql://168.192.11.555/product","root","root"); //执行的语句对象 String sql = "select * from Hero"; //执行者对象,可以理解为操作sql的对象 //1.执行DML语句也就是增啥改的操作使用 executeUpdate() 这个返回值是影响的数量 //2.执行DDL语句也就是查询的操作使用 executeQuery(); 这个返回的是结果集 //3.释放资源 preparedStatement = connection.prepareStatement(sql); //返回的结果集 //这边注意的就是要释放资源 resultSet = preparedStatement.executeQuery(); while(resultSet.next()){ System.out.println(resultSet.getString("name")); } } catch (Exception e) { e.printStackTrace(); }finally { try { if(resultSet !=null){ resultSet.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (preparedStatement!=null){ preparedStatement.close(); } } catch (SQLException e) { e.printStackTrace(); }if(connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } }}}}

2.JDBC工具类 - 手敲 这边实际上没有多少知识点。但是还是要手动敲一下记忆才深刻
import java.io.IOException; import java.io.InputStream; import java.sql.*; import java.util.Properties; public class JdbcUtils { //无参构造 private JdbcUtils(){}; //数据库链接的必要参数 private static String driverName; private static String url; private static String username; private static String password; private static Connection con; //从配置文件中读取数据然后加载到类里面static{ //获取输入流 InputStream resourceAsStream = JdbcUtils.class.getClassLoader().getResourceAsStream("mysqlProperties.properties"); //将流转化成对象 Properties properties = new Properties(); try { properties.load(resourceAsStream); driverName = properties.getProperty("driver"); url = properties.getProperty("url"); username = properties.getProperty("username"); password = properties.getProperty("password"); //让类加载,初始化哪个数据库 其实就是初始化DriverManager Class.forName(driverName); } catch (Exception e) { e.printStackTrace(); }finally { if (resourceAsStream !=null){ try { resourceAsStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }//创建链接public static Connection getConnection(){ try { con = DriverManager.getConnection(url, username, password); } catch (SQLException e) { e.printStackTrace(); }return con; }public static voidcloseConnection(Connection con, Statement statement, ResultSet resultSet){ if(con!=null){ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if(statement !=null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } }if (resultSet!=null){ try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } } //关闭资源 public static voidcloseConnection(Connection con, Statement statement){ if(con!=null){ try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if(statement !=null){ try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } } }

值得注意的是配置文件的路径
【Java|JDBC (Java DataBase Connectivity )的基本使用】Java|JDBC (Java DataBase Connectivity )的基本使用
文章图片

3.jdbc事务 这边很简单,知道一下就好。
//是否开启事务自动提交,这边false就是开启事务 connection.setAutoCommit(false); //提交事务 connection.commit(); //回滚事务 connection.rollback();

4.自定义数据库连接池 这边的重点主要是实现DataSource这个接口。
这边有个值得深思的问题,就是我调用con.close的方法如何不是关闭连接而是,返回线程池呢?
  1. 第一种的想法就是继承jdbcConnection的思维,但是最后是行不通的。因为需要改动的类太多了。工作量太大
  2. 装饰者模式,就是在返回连接对象的时候,再次封装成一个新的类,在这个方法里面重写con.close方法
  3. 适配器模式,实际上和装饰者模式差不多的思维,只是多了一个中间的抽象类,这个抽象类里面还是调用除了close以外的方法。
  4. 动态代理模式。这是最好的方法,也是各个持久层框架里面常用的方法。后面我会介绍一下
import javax.sql.DataSource; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Logger; /** * 自定义数据库链接池,简单版 */ public class MyJdbcPool implements DataSource { //创建一个线程安全的连接池 private static List pool = Collections.synchronizedList(new ArrayList<>()); //初始化十条连接 static{ for (int i = 0; i < 10; i++) { Connection connection = JdbcUtils.getConnection(); pool.add(connection); } } @Override public Connection getConnection() throws SQLException { if(pool.size()>0){ Connection connection = pool.remove(0); return connection; }else{ new RuntimeException("数据库连接池耗尽"); } return null; }@Override public Connection getConnection(String username, String password) throws SQLException { return null; }@Override public T unwrap(Class iface) throws SQLException { return null; }@Override public boolean isWrapperFor(Class iface) throws SQLException { return false; }@Override public PrintWriter getLogWriter() throws SQLException { return null; }@Override public void setLogWriter(PrintWriter out) throws SQLException {}@Override public void setLoginTimeout(int seconds) throws SQLException {}@Override public int getLoginTimeout() throws SQLException { return 0; }@Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } }

4.1 动态代理返回连接池 这是基于上面连接池的类修改的,那么我们这边就是对close做动态增强。让他返回连接池而不是关闭连接。
@Override public Connection getConnection() throws SQLException { if(pool.size()>0){ Connection connection = pool.remove(0); Connection proxyInstance = (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("close")) { System.out.println("归还连接池"); pool.add(connection); return null; } else { return method.invoke(connection, args); } } }); return proxyInstance; }else{ new RuntimeException("数据库连接池耗尽"); } return null; }

5.结束语 以上就是jdbc、以及连接池的基本使用,当然这边写的连接池只是丐版,很多不完善,诸如c3p0、druid等连接池都是很完善的数据连接池框架。但是实现的思路都是差不多的,感兴趣的同学可以看一下源码。提高自身的编码能力的唯一途径就是多看,多写。
最后还是要提示一下ResultSet是有专门的方法获取返回的值对象,然后通过反射的方式可以生成对应的bean对象。然后预处理对象也有专门的方法可以获取里面占位符的个数,从而和传入的对象进行一对一的赋值。jdbc高级部分有时间可以再次了解一下。


如有错误,多多指正!

    推荐阅读