• 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
      }
    }
    
    
  • 相关阅读:
    Thread的run方法和start方法
    35. Search Insert Position
    Error:(1, 1) java: 非法字符: 'ufeff'
    final修饰的变量是引用不可变,还是对象不可变
    数组与练习
    java反射机制【转】
    Socket
    面向对象的设计原则和设计模式
    多线程
    为什么有时候修改了css文件,页面的样式却没有改变?
  • 原文地址:https://www.cnblogs.com/sgs123/p/14119529.html
Copyright © 2020-2023  润新知