JDBC入门

一.JDBC概述

JDBC全称为:Java DataBase Connectivity(Java数据库连接)

二.JDBC入门

1.搭建开发环境
#创建数据库
create database jdbctest;
use jdbctest;
create table user(
	uid int primary key auto_increment,
    username varchar(20),
    password varchar(20),
    name varchar(20)
);
insert into user values (null,'aaa','111','张三');
insert into user values (null,'bbb','222','李四');
insert into user values (null,'ccc','333','王五');
2.编写程序,在程序中加载数据库驱动
//DriverManager.registerDriver(new Driver());
Class.forName("com.mysql.jdbc.Driver");
3.建立连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest","root","123456");
4.创建用于向数据库发送SQL的statement对象
String sql = "select * from user";
Statement stmt = conn.createStatement();
5.从代表结果集的ResultSet中取出数据
ResultSet result = stmt.executeQuery(sql);
while(result.next()){
    int uid = resultSet.getInt("uid");
    String username = resultSet.getString("username");
    String password = resultSet.getString("password");
    String name = resultSet.getString("name");
    System.out.println(uid+"   "+username+"   "+password+"   "+name);
}
6.断开与数据库的连接,并释放相关资源
result.close();
stmt.close();
conn.close();

三.JDBC的API

1.DriverManager驱动管理类
  • 主要作用

    • 注册驱动

      • 实际开发中注册驱动会使用如下的方式:

        Class.forName("com.mysql.jdbc.Driver");
        
      • 因为之前的方式会导致驱动注册两次

    • 获得连接

      Connection getConnection(String url,String username,String password);
      
      • url写法:jdbc:mysql://localhost:3306/jdbc
        • Jdbc:协议
        • mysql:子协议
        • localhost:主机名
        • 3306:端口号
      • url简写(主机为本机):jdbc:mysql:///jdbc
2.Connection连接对象
  • 主要作用
    • 创建执行SQL语句的对象
      • Statement createStatement()执行SQL语句,有SQL注入的漏洞存在
      • PreparedStatement prepareStatement(String sql)预编译SQL语句,解决SQL注入的漏洞
      • CallableStatement prepareCall(String sql)执行SQL中存储过程
    • 进行事务的管理
      • setAutoCommit(boolean autoCommit)设置事务是否自动提交
      • commit()事务提交
      • rollback()事务回滚
3.Statement执行SQL语句
  • 主要作用
    • 执行SQL语句
      • Boolean execute(String sql)执行SQL,执行select语句返回true,否则返回false
      • ResultSet executeQuery(String sql)执行SQL中的select语句
      • int executeUpdate(String sql)执行SQL中的insert/update/delete语句
    • 执行批处理操作
      • addBatch(String sql)添加批处理
      • executeBatch()执行批处理
      • clearBatch()清理批处理
4.ResultSet结果集
  • 结果集:其实就是查询语句(select)语句查询的结果的封装
  • 主要作用:
    • 结果集获取查询到的结果
      • next()判断是否有下一行记录,如果有则将光标移到下一行
      • 针对不同的类型的数据可以使用getXXX()获取数据,通用的获取数据的方法getObject()

四.JDBC的资源释放

  • JDBC程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet,Statement和Connection对象

  • 特别是Connectiion对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。

  • 在finally中释放资源

    if(rs!=null){
        try{
            rs.close();
        }catch(SQLException e){
            e.printStackTrace();
        }
        rs = null;//close后,资源还没有被回收。如果手动将其置为null则垃圾回收机制更早回收对象。
    }
    if(stmt!=null){
        try{
            stmt.close();
        }catch(SQLException e){
            e.printStackTrace();
        }
        stmt = null;
    }
    if(conn!=null){
        try{
            conn.close();
        }catch(SQLException e){
            e.printStackTrace();
        }
        conn = null;
    }
    

五.JDBC的CRUD操作

1.向数据库中保存记录
public void demo1 () {
		Connection conn = null;
		Statement stmt = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest","root","123456");
			stmt = conn.createStatement();
			String sql = "insert into user values(null,'eee','123','孙柳')";
			int i = stmt.executeUpdate(sql);
			if(i>0) {
				System.out.println("保存成功!");
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			//释放资源
			if(stmt!=null){
			    try{
			        stmt.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    stmt = null;
			}
			if(conn!=null){
			    try{
			        conn.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    conn = null;
			}
		}
	}
2.修改数据库中的记录
public void demo2() {
		 Connection conn = null;
		 Statement stmt = null;
		 try {
			 //注册驱动
			 Class.forName("com.mysql.jdbc.Driver");
			 //获得连接
			 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest","root","123456");
			 //创建执行SQL语句的对象
			 stmt = conn.createStatement();
			 //编写SQL语句
			 String sql = "update user set username = 'qqq',password='456',name='赵六' where uid = 4";
			 //执行SQL语句
			 int i = stmt.executeUpdate(sql);
			 if(i>0) {
				 System.out.println("修改成功!");
			 }
		 }catch(Exception e) {
			 e.printStackTrace();
		 }finally {
			//释放资源
			if(stmt!=null){
			    try{
			        stmt.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    stmt = null;
			}
			if(conn!=null){
			    try{
			        conn.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    conn = null;
			}
		 }
	}
3.删除数据库中的记录
public void demo3() {
		 Connection conn = null;
		 Statement stmt = null;
		 try {
			 //注册驱动
			 Class.forName("com.mysql.jdbc.Driver");
			 //获得连接
			 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest","root","123456");
			 //创建执行SQL语句的对象
			 stmt = conn.createStatement();
			 //编写SQL语句
			 String sql = "DELETE FROM user WHERE uid = 5";
			 //执行SQL语句
			 int i = stmt.executeUpdate(sql);
			 if(i>0) {
				 System.out.println("删除成功!");
			 }
		 }catch(Exception e) {
			 e.printStackTrace();
		 }finally {
			//释放资源
			if(stmt!=null){
			    try{
			        stmt.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    stmt = null;
			}
			if(conn!=null){
			    try{
			        conn.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    conn = null;
			}
		 }
	}
4.查询数据库中的记录
//查询多条记录
public void demo4() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql:///jdbctest","root","123456");
			stmt = conn.createStatement();
			String sql = "SELECT * FROM user";
			rs = stmt.executeQuery(sql);
			while(rs.next()) {
				int uid = rs.getInt("uid");
				String username = rs.getString("username");
				String password = rs.getString("password");
				String name = rs.getString("name");
				System.out.println("uid:"+uid+"  username:"+username+"  password:"+password+"  name:"+name);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(rs!=null){
			    try{
			        rs.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    rs = null;//close后,资源还没有被回收。如果手动将其置为null则垃圾回收机制更早回收对象。
			}
			if(stmt!=null){
			    try{
			        stmt.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    stmt = null;
			}
			if(conn!=null){
			    try{
			        conn.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    conn = null;
			}
		}
	}

//查询一条记录
public void demo5() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql:///jdbctest","root","123456");
			stmt = conn.createStatement();
			String sql = "SELECT * FROM user where uid = 2";
			rs = stmt.executeQuery(sql);
			if(rs.next()) {
				int uid = rs.getInt("uid");
				String username = rs.getString("username");
				String password = rs.getString("password");
				String name = rs.getString("name");
				System.out.println("uid:"+uid+"  username:"+username+"  password:"+password+"  name:"+name);
			}
		}catch(Exception e) {
			e.printStackTrace();
		}finally {
			if(rs!=null){
			    try{
			        rs.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    rs = null;//close后,资源还没有被回收。如果手动将其置为null则垃圾回收机制更早回收对象。
			}
			if(stmt!=null){
			    try{
			        stmt.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    stmt = null;
			}
			if(conn!=null){
			    try{
			        conn.close();
			    }catch(SQLException e){
			        e.printStackTrace();
			    }
			    conn = null;
			}
		}
	}

六.JDBC的工具类的抽取

  • 为了简化JDBC的开发,可以将一些重复的代码进行提取

  • 定义JDBCUtils.java工具类

    import java.io.IOException;
    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 JDBCUtils {
    	private static final String driverClass;
    	private static final String url;
    	private static final String username;
    	private static final String password;
    	
    	static {
    		//加载属性文件并解析
    		Properties props = new Properties();
    		//获得属性文件的输入流
    		//通常采用类加载器方式的进行获取
    		InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
    		try {
    			props.load(is);
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		driverClass=props.getProperty("driverClass");
    		url=props.getProperty("url");
    		username=props.getProperty("username");
    		password=props.getProperty("password");
    	}
    	
    	/**
    	 * 注册驱动
    	 */
    	public static void loadDriver() throws ClassNotFoundException{
    		Class.forName(driverClass);
    	}
    	
    	/**
    	 * 获得连接的方法
    	 * @return
    	 * @throws SQLException
    	 * @throws ClassNotFoundException 
    	 */
    	public static Connection getConnection() throws SQLException, ClassNotFoundException {
    		loadDriver();
    		Connection conn = DriverManager.getConnection(url,username,password);
    		return conn;
    	}
    	
    	/**
    	 * 资源释放
    	 * @param stmt
    	 * @param conn
    	 * @throws SQLException 
    	 */
    	public static void release(Statement stmt, Connection conn) throws SQLException {
    		if(stmt != null) {
    			try {
    				stmt.close();
    			}catch(SQLException e) {
    				e.printStackTrace();
    			}
    			stmt = null;
    		}
    		if(conn != null) {
    			try {
    				conn.close();
    			}catch(SQLException e) {
    				e.printStackTrace();
    			}
    			conn = null;
    		}
    	}
    	
    	/**
    	 * 资源释放
    	 * @param rs
    	 * @param stmt
    	 * @param conn
    	 */
    	public static void release(ResultSet rs,Statement stmt,Connection conn) {
    		if(rs != null) {
    			try {
    				rs.close();
    			}catch(SQLException e) {
    				e.printStackTrace();
    			}
    			rs = null;
    		}
    		
    	}	
    }
    
  • 定义Properties文件

    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql:///jdbctest
    username=root
    password=123456
    
  • 定义测试文件

    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.Statement;
    import org.junit.Test;
    public class JDBCDemo3 {
    
    	@Test
    	//保存记录
    	public void demo1() throws SQLException {
    		Connection conn = null;
    		Statement stmt = null;
    		try {
    			//获得连接
    			conn = JDBCUtils.getConnection();
    			//创建执行
    			stmt = conn.createStatement();
    			//编写sql语句
    			String sql = "insert into user values (null,'ppp','123','小六')";
    			int num = stmt.executeUpdate(sql);
    			if(num > 0) {
    				System.out.println("保存成功!");
    			}
    		}catch(Exception e) {
    			e.printStackTrace();
    		}finally {
    			JDBCUtils.release(stmt, conn);
    		}
    	}	
    }
    

七.SQL注入漏洞

  • SQL漏洞产生
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Test;

public class JDBCDemo4 {

	public static boolean login(String username, String password) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		boolean flag=false;
		//获得连接
		try {
			conn = JDBCUtils.getConnection();
			//创建执行
			stmt = conn.createStatement();
			//编写sql语句
			String sql ="select * from user where username='"+username+"' and password = '"+password+"'";
			//执行sql语句
			rs = stmt.executeQuery(sql);
			//判断结果集中是否有数据
			if(rs.next()) {
				flag = true;
			}else {
				flag = false;
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			JDBCUtils.release(rs,stmt, conn);
		}
		return flag;
	}
	
	@Test
	public void demo1() {
		if(JDBCDemo4.login("aaa ' or '1=1", "suibianxie")) {//SQL注入方式
			System.out.println("登录成功");
		}else {
			System.out.println("登录失败");
		}
	}	
}
  • SQL注入漏洞的解决

    • 使用预处理对象preparedStatement

    • preparedStatement是Statement的子接口,它的实例对象可以通过调用Connection.preparedStatement(sql)方法获得,相对于Statement对象而言

      • PreparedStatement可以避免SQL注入的问题。
      • Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。
      • 并且PreparedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。
    • 避免SQL注入漏洞的方法

      public static boolean login2(String username,String password) {
          Connection conn = null;
          PreparedStatement pstmt = null;
          ResultSet rs = null;
          boolean flag = false;
          try {
              //获得连接
              conn = JDBCUtils.getConnection();
              //编写SQL
              String sql = "select * from user where username = ? and password = ?";
              //预处理SQL
              pstmt = conn.prepareStatement(sql);
              //设置参数
              pstmt.setString(1, username);
              pstmt.setString(2, password);
              //执行SQL
              rs = pstmt.executeQuery();
              //判断结果集
              if(rs.next()) {
                  flag = true;
              }else {
                  flag = false;
              }
          }catch(Exception e) {
              e.printStackTrace();
          }finally {
              JDBCUtils.release(rs, pstmt, conn);
          }
          return flag;
      }
      
  • PreparedStatement的使用

    • 保存数据

      public void demo1() throws SQLException {
          Connection conn = null;
          PreparedStatement pstmt = null;
          try {
              //获得连接
              conn = JDBCUtils.getConnection();
              //编写SQL
              String sql = "insert into  user values (null,?,?,?)";
              //预处理SQL
              pstmt = conn.prepareStatement(sql);
              //设置具体的参数值
              pstmt.setString(1, "qqq");
              pstmt.setString(2, "123");
              pstmt.setString(3, "张武");
              //执行sql语句
              int num = pstmt.executeUpdate();
              if(num>0) {
                  System.out.println("保存成功!");
              }
          }catch(Exception e) {
              e.printStackTrace();
          }finally {
              JDBCUtils.release(pstmt, conn);
          }
      }
      
    • 修改数据

      public void demo2() throws SQLException {
          Connection conn = null;
          PreparedStatement pstmt = null;
          try {
              //获得连接
              conn = JDBCUtils.getConnection();
              //编写SQL
              String sql = "update user set username = ?, password = ?, name = ? where uid =?";
              //预处理SQL
              pstmt = conn.prepareStatement(sql);
              //设置参数
              pstmt.setString(1, "www");
              pstmt.setString(2, "123456");
              pstmt.setString(3, "张柳");
              pstmt.setInt(4, 9);
              //执行SQL
              int num = pstmt.executeUpdate();
              if(num>0) {
                  System.out.println("修改成功");
              }
          }catch(Exception e) {
              e.printStackTrace();
          }finally {
              JDBCUtils.release(pstmt, conn);
          }
      }
      
    • 删除数据

      public void demo3() throws SQLException {
          Connection conn = null;
          PreparedStatement pstmt = null;
          try {
              //获得连接
              conn = JDBCUtils.getConnection();
              //编写SQL
              String sql = "delete from user where uid = ?";
              //预处理SQL
              pstmt = conn.prepareStatement(sql);
              //设置参数
              pstmt.setInt(1, 9);
              //执行SQL
              int num = pstmt.executeUpdate();
              if(num>0) {
                  System.out.println("删除成功");
              }
          }catch(Exception e) {
              e.printStackTrace();
          }finally {
              JDBCUtils.release(pstmt, conn);
          }
      }
      
    • 查询所有数据

      public void demo4() throws SQLException {
          Connection conn = null;
          PreparedStatement pstmt = null;
          ResultSet rs = null;
          try {
              //获得连接
              conn = JDBCUtils.getConnection();
              //编写SQL
              String sql = "select * from user";
              //预处理SQL
              pstmt = conn.prepareStatement(sql);
              //执行SQL
              rs = pstmt.executeQuery();
              while(rs.next()) {
                  System.out.println(rs.getInt("uid")+"   "+rs.getString("username")+"   "+rs.getString("password")+"   "+rs.getString("name"));
              }
          }catch(Exception e) {
              e.printStackTrace();
          }finally {
              JDBCUtils.release(rs,pstmt, conn);
          }
      }
      

八.数据库连接池

  • 连接池

    • 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用
    • 传统直接获取连接的缺点:用户每次请求都需要向数据库获得连接通常需要消耗相对大的资源,创建时间也比较长。访问量增大极易造成数据库服务器内存溢出。
  • C3P0连接池的使用

    • 手动设置连接池操作

      package com.imooc.jdbc;
      
      import java.beans.PropertyVetoException;
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      
      import org.junit.Test;
      
      import com.mchange.v2.c3p0.ComboPooledDataSource;
      
      /**
       * 连接池的测试类
       * @author wangzhe
       *
       */
      public class DataSourceDemo1 {
      	@Test
      	/**
      	 * 手动设置连接池
      	 */
      	public void demo1() throws PropertyVetoException {
      		//创建连接池
      		ComboPooledDataSource dataSource = new ComboPooledDataSource();
      		//设置连接池参数
      		dataSource.setDriverClass("com.mysql.jdbc.Driver");
      		dataSource.setJdbcUrl("jdbc:mysql:///jdbctest");
      		dataSource.setUser("root");
      		dataSource.setPassword("123456");
      		dataSource.setMaxPoolSize(20);//设置最大连接池个数
      		dataSource.setInitialPoolSize(3);//设置初始化连接池个数
      		//获得连接
      		Connection conn = null;
      		PreparedStatement pstmt = null;
      		ResultSet rs = null;
      		try {
      			//获得连接
      			conn = dataSource.getConnection();//从连接池中获得
      			//编写SQL
      			String sql = "select * from user";
      			//预编译SQL
      			pstmt = conn.prepareStatement(sql);
      			//设置参数:无参数
      			//执行SQL
      			rs = pstmt.executeQuery();
      			while(rs.next()) {
      				System.out.println(rs.getInt("uid")+"   "+rs.getString("username")+"   "+rs.getString("password")+"   "+rs.getString("name"));
      			}
      		}catch(Exception e) {
      			e.printStackTrace();
      		}finally {
      			JDBCUtils.release(rs, pstmt, conn);
      		}
      	}
      }
      
    • 使用配置文件的方式

      //c3p0的配置文件:c3p0-config.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <c3p0-config>
      
        <default-config>
          <property name="driverClass">com.mysql.jdbc.Driver</property>
      	<property name="jdbcUrl">jdbc:mysql:///jdbctest</property>
      	<property name="user">root</property>
      	<property name="password">123456</property>
      	<property name="initialPoolSize">5</property>
      	<property name="maxPoolSize">20</property>
        </default-config>
        
      </c3p0-config>
      
      //使用配置文件的方式
      @Test
      	public void demo2() throws PropertyVetoException {
      		//创建连接池
      		ComboPooledDataSource dataSource = new ComboPooledDataSource();//自动找classpath下的配置文件
      		//获得连接
      		Connection conn = null;
      		PreparedStatement pstmt = null;
      		ResultSet rs = null;
      		try {
      			//获得连接
      			conn = dataSource.getConnection();//从连接池中获得
      			//编写SQL
      			String sql = "select * from user";
      			//预编译SQL
      			pstmt = conn.prepareStatement(sql);
      			//设置参数:无参数
      			//执行SQL
      			rs = pstmt.executeQuery();
      			while(rs.next()) {
      				System.out.println(rs.getInt("uid")+"   "+rs.getString("username")+"   "+rs.getString("password")+"   "+rs.getString("name"));
      			}
      		}catch(Exception e) {
      			e.printStackTrace();
      		}finally {
      			JDBCUtils.release(rs, pstmt, conn);
      		}
      	}
      
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值