JDBC使用+数据库连接池+springJDBC

一、JDBC基本概念和下载

JDBC(Java DataBase Connectivity),通俗来讲就是用java语言操作数据库

  • 本质
    sun公司定义的一套操作所有关系型数据库的规则,即接口。
    各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。
下载

去mysql官网下载其他版本

点击直接下载5.1.40
下载截图:

二、详细步骤

环境准备

在mysql中创建一个db3的数据库,并创建一个user表插入几条用户信息的数据

-- 创建一个编码为utf8 的数据库db3
create database db3 character set utf8;
use db3;

-- 创建user表
create table user (
	id int primary key auto_increment, 
	name varchar(32), -- 用户名
	password varchar(32) -- 密码
);

-- 添加一条数据
insert into user ( name, password ) values ( 'zhangsan', 123456 );
工程导入驱动jar包
  • 1、下载之后解压
  • 2、复制mysql的驱动包mysql-connector-java-5.1.40-bin.jar到工程上新建的lib目录下
  • 3、右键.jar文件,选择add As Library 添加成库

1、加载数据库驱动

//注册驱动
Class.forName("com.mysql.jdbc.Driver");

2、建立连接

String url = "jdbc:mysql://localhost:3306/db3";			
String userName = "root";			
String password = "root";			
//获取与数据库的链接
Connection conn = DriverManager.getConnection(url, userName, password);

注意:如果是localhost:3306, mysql可以简写为jdbc:mysql:///db3

  • connection 对象常用方法:
方法 描述
createStatement() 创建可执行sql的statement对象(容易产生sql注入问题)
prepareStatement(sql) sql参数使用?作占位符,返回一个预编译后的prepareStatement对象(解决了sql注入问题)
setAutoCommit(boolean autoCommit) 设置事务是否自动提交:在执行sql之前开启事务
commit() 提交事务:当所有sql都执行完提交事务
rollback() 回滚事务:在catch中回滚事务

3、执行SQL语句

  • Statement 对象常用方法:
方法 描述
boolean execute(String sql) 可执行任意的sql语句,返回布尔值(一般不用)
int executeUpdate(String sql) 执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句,返回影响的行数(常用)
ResultSet executeQuery(String sql) 执行DQL(select)语句,返回一个ResultSet对象(常用)
//使用statement 如:添加一条用户数据
//1、定义sql语句
String sql = "insert into user ( name, password ) values ( 'lisi', 1234 )";
//2、获取执行sql语句的对象
Statement st = conn.createStatement();
//3、定义sql语句并执行 如果count>0 则表示添加成功,否则添加失败
int count = st.executeUpdate(sql);

//推荐使用prepareStatement,如:查询登录用户是否匹配
//1、定义sql语句
String sql = "select * from user where name=? and password=?";
//2、获取执行sql语句的对象,需要传入sql,进行预编译
PrepareStatement pst = conn.prepareStatement(sql);
//3、设置值setXxx, Xxx代表获取字段的类型,如:setInt、setString
pst.setString(1, "lisi");
pst.setString(2, "1234");
//4、执行sql,不需要传递sql,直接返回结果对象
ResultSet rs = pst.executeQuery();

if(rs.next()){
  //登录成功
}

4、获取查询的结果集

  • ResultSet常用方法
//1、获取行,返回末尾是否有数据, 有则返回false,没有返回true
boolean next() //游标向下移动一行

//2.获取数据 Xxx 代表数据类型。 如:getInt(1) getString("name")
//根据列的编号获取值 从1开始
getXxx(int index);
//根据列的名称获取值
getXxx(String columName);

5、释放资源

1、需要释放的对象:ResultSet 结果集,Statement 语句,Connection 连接。
2、释放原则:先开的后关,后开的先关。ResultSet --> Statement --> Connection。
3、在finally中执行。

ResultSet rs = null;
Statement st = null;
Connection conn = null;
try{
  //JDBC操作数据库代码实现
}catch{
  //异常处理
}finally{
  if(rs != null){
    try {
      rs.close();
    } catch (SQLException throwables){
      throwables.printStackTrace();
    }
  }
  if(stm != null){
    try {
        stm.close();
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
  }
  if(conn != null){
    try {
        conn.close();
    } catch (SQLException throwables) {
        throwables.printStackTrace();
    }
  }
}

三、JDBC实现工具类 jdbcUtils

1、在src问件下创建一个jdbc.properties文件,用于修改配置文件,而不用修改代码

加上?characterEncoding=utf8 可以解决中文乱码问题

url=jdbc:mysql://localhost:3306/db3?characterEncoding=utf8
username=root
password=root
driver=com.mysql.jdbc.Driver
2、创建一个utils包,在包下创建一个JdbcUtils类

主要实现的方法:

  • 1、得到数据库的连接对象 getConnection()
    • 使用配置文件代替传递的参数
  • 2、关闭所有打开的资源
    • close(PreparedStatement pst, Connection conn)、
    • close(ResultSet rs, PreparedStatement pst, Connection conn)
package com.yj.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
    private static String url = null;
    private static String username = null;
    private static String password = null;
    private static String driver = null;

    //文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
    static {
        try {
            //1、创建properties集合类
            Properties pro = new Properties();
            //2、获取src路径下的jdbc.properties文件的方式--->ClassLoader 类加载器
            InputStream rs = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            //3、加载文件
            pro.load(rs);
            //4、获取值并赋值
            url = pro.getProperty("url");
            username = pro.getProperty("username");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");
            //5、注册驱动
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 得到数据库连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }

    //关闭所有打开的资源
    public static void close(PreparedStatement pst, Connection conn){
        if(pst != null){
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(ResultSet rs, PreparedStatement pst, Connection conn){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(pst != null){
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
3、使用工具类对db3数据库进行CRUD
package com.yj.jdbc;

import com.yj.utils.JdbcUtils;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Demo02 {
    //向数据库新增一条用户数据
    @Test
    public void insert(){
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "insert into user (name, password) values (?, ?)";
            pst = conn.prepareStatement(sql);
            pst.setString(1,"王五");
            pst.setString(2,"123");
            int count = pst.executeUpdate();
            if(count > 0){
                System.out.println("添加成功");
            }else{
                System.out.println("添加失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(pst, conn);
        }
    }

    //修改数据 (修改id=2这条数据的密码为123456)
    @Test
    public void update (){
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "update user set password = ? where id = 2";
            pst = conn.prepareStatement(sql);
            pst.setString(1,"123456");
            int count = pst.executeUpdate();
            if(count > 0){
                System.out.println("修改成功");
            }else{
                System.out.println("修改失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(pst, conn);
        }
    }

    //删除数据 (删掉id=2这条数据)
    @Test
    public void delete(){
        Connection conn = null;
        PreparedStatement pst = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "delete from user where id = 2";
            pst = conn.prepareStatement(sql);
            int count = pst.executeUpdate();
            if(count > 0){
                System.out.println("删除成功");
            }else{
                System.out.println("删除失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(pst, conn);
        }
    }

    //查询 (查询id=1这条数据并打印所有字段)
    @Test
    public void retrieve(){
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "select * from user where id = ?";
            pst = conn.prepareStatement(sql);
            pst.setInt(1,1);
            rs = pst.executeQuery();
            if(rs.next()){
                System.out.println("id=" + rs.getInt("id"));
                System.out.println("name=" + rs.getString("name"));
                System.out.println("password=" + rs.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(rs, pst, conn);
        }
    }
}

四、使用数据库连接池

概念

其实就是一个容器(集合),存放数据库连接的容器。

好处
  • 1、节约资源。
  • 2、用户访问高效。
如何实现
  • 1、接口:DataSource 下:
    • 获取连接:getConnection()
    • 归还连接:close()
  • 2、一般我们不去实现它,由数据库厂商来实现,常用的有:

1、C3P0的使用

  • 1、导入jar包(两个)c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar,不要忘记导入数据库驱动的jar包
  • 2、定义配置文件
    • 名称:c3p0.properties 或者 c3p0-config.xml
    • 位置:src文件目录下
<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
  	<!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db3?characterEncoding=utf8</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <!--初始化申请的连接数量-->
    <property name="initialPoolSize">5</property>
    <!--最大的连接数量-->
    <property name="maxPoolSize">10</property>
    <!--超时时间-->
    <property name="checkoutTimeout">3000</property>
  </default-config>

  <!-- 使用name参数读取连接池对象 -->
  <named-config name="otherc3p0"> 
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db3?characterEncoding=utf8</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>
</c3p0-config>
  • 3、创建数据库连接对象:comboPooleDataSource
//ComboPooledDataSource(String name)传入参数代表上面带有name属性的配置
//不传为默认
DataSource ds = new ComboPooledDataSource(); 
  • 4、获取连接
Connection conn = ds.getConnection();

2、Druid的使用

  • 1、导入jar包 druid-1.0.9.jar

  • 2、定义配置文件,properties形式,任意名称,任意目录
    如:druid.properties

url=jdbc:mysql://localhost:3306/db3?characterEncoding=utf8
username=root
password=root
driver=com.mysql.jdbc.Driver
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
  • 3、加载配置文件
Properties pro = new Properties();
InputStrean is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
  • 4、获取数据库连接池对象:DruidDataSourceFactory
DataSource ds = DruidDataSourceFactory.createDataSource(pro);
  • 5、获取连接
Connection conn = ds.getConnection();
  • 6、也可以定义工具类来提高代码的复用性:只要实现获取连接,归还连接

五、Spring JDBC

提供了一个JDBCTemplate对象简化JDBC的开发

1、使用步骤

//ds为数据库连接对象
JdbcTemplate template = new JdbcTemplate(ds);
  • 3、调用JdbcTemplate的方法来完成CRUD的操作,不需要调用close方法
方法 描述
update() 执行DML语句。增、删、改语句
queryForMap() 将查询1条结果集封装为map集合,将列名作为key,将值作为value
queryForList() 查询结果将结果集封装为list集合(注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中)
query() 查询结果,将结果封装为JavaBean对象(参数RowMapper,一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装)
queryForObject() 将结果封装为对象,一般用于聚合函数的查询

2、代码实现一个简单的例子

准备表的数据
-- 删除表的内容
truncate table user; 

-- 添加一些数据
insert into user values (null, "张三", "abcd"), (null, "李四", "bbb"), (null, "王五", "ccc");
代码实现例子
    1. 修改1号数据的 password 为 aaa
    1. 添加一条记录
    1. 删除刚才添加的记录
    1. 查询id为1的记录,将其封装为Map集合
    1. 查询所有记录,将其封装为List
    1. 查询所有记录,将其封装为Emp对象的List集合
    1. 查询总记录数
public class Demo04 {
  //使用c3p0来创建数据库连接对象
  private JdbcTemplate template = new JdbcTemplate(new ComboPooledDataSource());

  //1. 修改1号数据的 password 为 aaa
  @Test
  public void test1(){
      String sql = "update user set password = 'aaa' where id = 1";
      int count = template.update(sql);
      if(count>0){
          System.out.println("修改成功");
      }
  }
  //2. 添加一条记录
  @Test
  public void test2(){
      String sql = "insert into user values (null, ?, ?)";
      int count = template.update(sql, "小明", "ddd");
      if(count>0){
          System.out.println("添加成功");
      }
  }
  // 3. 删除刚才添加的记录
  @Test
  public void test3(){
      String sql = "delete from user where id = ?";
      int count = template.update(sql, 4);
      if(count>0){
          System.out.println("删除成功");
      }
  }
  // 4. 查询id为1的记录,将其封装为Map集合
  @Test
  public void test4(){
      String sql = "select * from user where id = 1";
      Map<String, Object> map = template.queryForMap(sql);
      System.out.println(map); //{id=1, name=张三, password=aaa}
  }
  // 5. 查询所有记录,将其封装为List
  @Test
  public void test5(){
      String sql = "select * from user";
      List<Map<String, Object>> list = template.queryForList(sql);
      System.out.println(list);
      //[{id=1, name=张三, password=aaa}, {id=2, name=李四, password=bbb}, {id=3, name=王五, password=ccc}]
  }
  // 6. 查询所有记录,将其封装为Emp对象的List集合
  @Test
  public void test6(){
      String sql = "select * from user";
      List<User> list = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
      System.out.println(list);
      //[User{id=1, name='张三', password='aaa'}, User{id=2, name='李四', password='bbb'}, User{id=3, name='王五', password='ccc'}]
  }
  // 7. 查询总记录数
  @Test
  public void test7(){
      String sql = "select count(id) from user";
      Long total = template.queryForObject(sql, Long.class);
      System.out.println(total); //3
  }
}

posted @ 2020-12-11 11:37  smile_or  阅读(817)  评论(0编辑  收藏  举报