JDBC

JDBC

JDBC:java和数据库的连接,Sun公司定义的一套java操作数据库的接口规范。

快速入门

准备工作

  • 数据库准备
    create database mytestdb character set utf8;
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
    `uid` varchar(50) NOT NULL,
    `username` varchar(20) DEFAULT NULL,
    `password` varchar(50) DEFAULT NULL,
    `name` varchar(20) DEFAULT NULL,
    `email` varchar(30) DEFAULT NULL,
    `telephone` varchar(20) DEFAULT NULL,
    `birthday` date DEFAULT NULL,
    `sex` varchar(10) DEFAULT NULL,
    `state` int(11) DEFAULT NULL,
    `code` varchar(64) DEFAULT NULL,
    PRIMARY KEY (`uid`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    INSERT INTO `user` VALUES ('10d27af0-7dd7-456c-ac81-bacd4833490d', 'root', '123456', '管理员', 'root@126.com', null, '2017-07-01', 'man', null, null);
    INSERT INTO `user` VALUES ('1be0290a-c300-4bc1-8f67-de061904e60e', 'zhangsan', '123', '张三', 'zhangsan@126.com', null, '2017-07-18', 'woman', null, null);
    INSERT INTO `user` VALUES ('3e663996-83ac-4cda-ad79-b15080553837', 'lisi', '123', '李四', 'lisi@126.com', null, '2017-07-18', 'man', null, null);
    INSERT INTO `user` VALUES ('5814301c-463e-4b66-9dcb-fc1ed7c29341', 'wangwu', '123', '王五', 'wangwu@126.com', null, '2017-07-11', 'woman', null, null);
    INSERT INTO `user` VALUES ('7e1927b6-67b4-4250-a01c-d054e730dd34', 'admin', '123456', 'Administror', 'admin@163.com', null, '2017-07-05', 'woman', null, null);
    
  • 导入jar包
    比如:mysql-connector-java-5.0.8-bin.jar

    统计user表的中记录数

    /**
       * 快速入门
       * 获取user表中所有的记录书
       * @throws Exception 
       */
      @Test
      public void test01() throws Exception {
          // 1、注册驱动
          Class.forName("com.mysql.jdbc.Driver");
          // 2、 获取连接
          String url = "jdbc:mysql://127.0.0.1:3306/mytestdb";
          String user = "root";
          String password = "123456";
          Connection conn = DriverManager.getConnection(url, user, password);
          // 3、获取发送sql的对象
          Statement statement = conn.createStatement();
          // 4、执行sql,返回结果
          String sql = "select count(*) from user";
          ResultSet resultSet = statement.executeQuery(sql);
          // 5、处理结果
          while (resultSet.next()){
              int count = resultSet.getInt(1);
              System.out.println("user表中一共有"+count+"条数据");
          }
          // 6、关闭资源
          resultSet.close();
          statement.close();
          conn.close();
      }
    

    执行结果:user表中一共有5条数据

    修改表中的数据

    /**
       * 修改表的记录
       */
      @Test
      public void test02(){
          Connection conn = null;
          Statement statement = null;
          try {
              // 1、注册驱动
              Class.forName("com.mysql.jdbc.Driver");
              // 2、 获取连接
              String url = "jdbc:mysql://127.0.0.1:3306/mytestdb";
              String user = "root";
              String password = "123456";
              conn = DriverManager.getConnection(url, user, password);
              // 3、获取发送sql的对象
              statement = conn.createStatement();
              // 4、执行sql,返回结果
              String sql = "update user set name='哈哈' where uid='5814301c-463e-4b66-9dcb-fc1ed7c29341'";
              int num = statement.executeUpdate(sql);
              // 5、处理结果
              if (num > 0){
                  System.out.println("修改成功!");
              }else{
                  System.out.println("修改失败!");
              }
          } catch (Exception e) {
              e.printStackTrace();
          }finally {
              // 6、关闭资源
              try {
                  if (statement != null){
                      statement.close();
                  }
              } catch (SQLException e) {
                  e.printStackTrace();
              }
              try {
                  if (conn != null){
                      conn.close();
                  }
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
    
      }
    

    使用PreparedStatement,来方式sql注入的问题。

    /**
       * 使用PreparedStatement来解决sql注入的问题
       * 查询sex = woman的用户
       */
      @Test
      public void test03(){
          Connection conn = null;
          PreparedStatement prepareStatement = null;
          ResultSet rs = null;
          try {
              // 1、注册驱动
              Class.forName("com.mysql.jdbc.Driver");
              // 2、 获取连接
              String url = "jdbc:mysql://127.0.0.1:3306/mytestdb";
              String user = "root";
              String password = "123456";
              conn = DriverManager.getConnection(url, user, password);
              // 3、获取发送sql的对象
              String sql = "select * from user where sex=?";
              prepareStatement = conn.prepareStatement(sql);
              // 4、执行sql,返回结果
              prepareStatement.setString(1, "woman");
              rs = prepareStatement.executeQuery();
              // 5、处理结果
              while (rs.next()){
                  System.out.println(rs.getString("username")+"==="+rs.getString("password"));
              }
          } catch (Exception e) {
              e.printStackTrace();
          }finally {
              // 6、关闭资源
              try {
                  if (rs != null){
                      rs.close();
                  }
              } catch (SQLException e1) {
                  e1.printStackTrace();
              }
              try {
                  if (prepareStatement != null){
                      prepareStatement.close();
                  }
              } catch (SQLException e) {
                  e.printStackTrace();
              }
              try {
                  if (conn != null){
                      conn.close();
                  }
              } catch (SQLException e) {
                  e.printStackTrace();
              }
          }
    
      }
    

    使用c3p0连接池:

  • 配置文件,必须放在src目录下,名称为: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://localhost:3306/mytestdb</property>
      <property name="user">root</property>
      <property name="password">123456</property>
    
    </default-config>
    
    <!-- This app is massive! -->
    <named-config name="store"> 
        <property name="driverClass">com.mysql.jdbc.Driver</property>
      <property name="jdbcUrl">jdbc:mysql://localhost:3306/store</property>
      <property name="user">root</property>
      <property name="password">123456</property>
    </named-config>
    </c3p0-config>
    
  • 使用c3p0连接池完成查询

    /**
       * 使用c3p0完成查询工作
       */
      @Test
      public void test04() throws Exception {
          // 创建连接池
          ComboPooledDataSource dataSource = new ComboPooledDataSource();
          // 从连接池中获取连接
          Connection conn = dataSource.getConnection();
          // 获取发送sql的对象
          Statement statement = conn.createStatement();
          // 执行sql,返回结果
          String sql = "select count(*) from user";
          ResultSet resultSet = statement.executeQuery(sql);
          // 处理结果
          while (resultSet.next()) {
              int count = resultSet.getInt(1);
              System.out.println("user表中一共有" + count + "条数据");
          }
          // 关闭资源
          resultSet.close();
          statement.close();
          conn.close();
    
      }
    

    创建jdbc的工具类

    public class JDBCUtils {
      private static ComboPooledDataSource ds = new ComboPooledDataSource();
      private static ThreadLocal<Connection> tl = new ThreadLocal<>();
    
      //返回连接池
      public static DataSource getDataSource(){
          return ds;
      }
    
      /**
       * 返回一个连接,此连接与当前线程绑定了
       * 可以保证 此线程拿到的线程都是同一个
       * @return
       * @throws Exception
       */
      public static Connection getConnection() throws Exception {
          Connection conn = tl.get();
          if (conn == null){
              conn = ds.getConnection();
              tl.set(conn);
          }
          return conn;
      }
    }
    

    使用DBUtils来简化JDCB操作

      /**
       * 使用DBUtils来统计user表中的记录数
       */
      @Test
      public void test05(){
          // 利用工具类获取连接池,创建QueryRunner对象
          QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
          String sql = "select count(*) from user";
          try {
              Number number = qr.query(sql, new ScalarHandler<Number>());
              System.out.println("user表中共有"+number.intValue()+"条记录。");
          } catch (SQLException e) {
              e.printStackTrace();
          }
          /**
           * 这里不用释放连接,DBUtils会自动关闭,如果创建QueryRunner对象没有参数时,如下:
           * QueryRunner qr = new QueryRunner()
           * 这时,需要自己关闭连接
           */
      }
    

    事务的特性(ACID)

  • A:原子性:事务是一个整体,不可分割
  • C:一致性: 事务执行前和执行后,数据库必须处于一致的状态;如果事务执行成功,数据库的所有变化都将发生变化;如果事务执行失败,数据库的变化都将回滚,回到原始状态
  • I:隔离性: 多用户进行并发访问时,一个用户的事务,不能被其他用户的事务干扰,多个事务之间是互相隔离的。多个事务时事件是独立的,不能互相干扰
  • D:持久性: 一旦事务提交,它对数据库的改变将是持久性的

    如果不考虑事务的隔离性,将发生:脏读,不可重复度,幻读/虚读

  • 脏读: 一个事务读取到其他事务未提交的数据
  • 不可重复度: 一个事务多次读取表中的数据,结果不一样;读取了其它事务已经提交的数据(强调的数据被update)
  • 幻读: 一个事务读取到了其他事务提交的数据(强调的是记录数的变化,insert,delete)

    数据库的隔离级别

  • read uncnmitted 读未提交 问题:脏读,不可重复读,幻读
  • read cnmitted 读已提交 问题: 不可重复读,幻读 (oracle默认的级别)
  • repeatable read 可重复读 问题: 幻读 (mysql默认的级别)
  • serializable 串行化
原文地址:https://www.cnblogs.com/xiaoshitoutest/p/7326908.html