学习Mybatis前的Jdbc的复习~

 

JDBC

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。

导入mysql-connector-java-5.1.49

建立测试库

 
CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;
​
USE jdbcStudy;
​
CREATE TABLE `users`(
id INT PRIMARY KEY,
NAME VARCHAR(40),
PASSWORD VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
​
INSERT INTO `users`(id,NAME,PASSWORD,email,birthday)
VALUES(1,'zhansan','123456','zs@sina.com','1980-12-04'),
(2,'lisi','123456','lisi@sina.com','1981-12-04'),
(3,'wangwu','123456','wangwu@sina.com','1979-12-04')

  

 

jdbc测试

骤:

  1. 加载驱动

  2. 链接数据库DriverManager

  3. 获得执行sql的对象 statement

  4. 获得返回的结果集

  5. 施放链接

注意:报错可能原因:

  • &没有替换为&amp

  • useSSL没有放在最前

  上述两点改掉一点就正常了,也不知道为什么

import java.sql.*;
​
public class test1 {
    public static void main(String[] args) throws Exception {
        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        //用户信息和url
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?        useSSL=false&useUnicode=true&characterEncoding=utf8";
        String username="root";
        String password="123456";
        //链接成功 数据库对象
        Connection connection = DriverManager.getConnection(url,username,password);
        //执行SQL的对象
        Statement statement = connection.createStatement();
        //执行SQL的对象 去执行SQL 可能返回结果
        String sql="select * from users";
        ResultSet resultSet =  statement.executeQuery(sql);//返回的结果集
        while (resultSet.next()){
            System.out.println("id="+resultSet.getObject("id"));
            System.out.println("name="+resultSet.getObject("name"));
        }
        //施放链接
        resultSet.close();
        statement.close();
        connection.close();
​
    }
}

  


  • DriverManager

//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");

  

  • url

    String url = "jdbc:mysql://localhost:3306/jdbcstudy?useSSL=false&useUnicode=true&characterEncoding=utf8";
    //mysql--3306
    // 协议://主机地址:端口号/数据库名?参数1&参数2...
    //oracle--1521
    //jdbc:oracle:thin:@localhost:1521:sid
    

      

  • Connection
    //链接成功 数据库对象 connection代表数据库
    Connection connection = DriverManager.getConnection(url,username,password);
    connection.rollback();
    connection.rollback();
    connection.setAutoCommit();
    

      

  • Statement
 statement.executeQuery();//查询操作 返回结果集ResultSet
 statement.execute();//可以执行任何sql
 statement.executeUpdate();//更新 插入 删除都是用这个,返回受影响的行数

  


  • ResultSet

    //不知道类型就用Object
    resultSet.getObject();
    //知道类型可以直接使用对应类型获取
    resultSet.getString();
    resultSet.getInt();
    resultSet.getFloat();
    resultSet.getDouble();
    resultSet.next();//移动到下一行数据
    resultSet.beforeFirst();//移动到最前
    resultSet.afterLast();//移动到最后
    resultSet.previous();//移动到前一行
    resultSet.absolute(i);//移动到第i行
    

      

    2、 代码实现

  • 工具类

    //db.properties存储信息降低耦合
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/jdbcstudy?useSSL=false&useUnicode=true&characterEncoding=utf8
    username=root
    password=root
    import java.io.InputStream;
    import java.sql.*;
    import java.util.Properties;
    ​
    public class JdbcUtils {
        private static  String driver=null;
        private static  String url=null;
        private static  String username=null;
        private static  String password=null;
        static {
            try {
                InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
    ​
                Properties properties=new Properties();
                assert in != null;
                properties.load(in);
                driver=properties.getProperty("driver");
                url=properties.getProperty("url");
                username=properties.getProperty("username");
                password=properties.getProperty("password");
                //驱动只用加载一次
                Class.forName(driver);
    ​
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    ​
        //获取连接
        public static Connection getConnection() throws SQLException {
            return DriverManager.getConnection(url,username,password);
        }
        //施放资源
        public  static void release(Connection connection, Statement statement, ResultSet resultSet) throws Exception {
            if (resultSet!=null){
                resultSet.close();
            }
            if (statement!=null){
                statement.close();
            }
            if (connection!=null){
                connection.close();
            }
        }
    }
    

      

     

  • 操作

    import utils.JdbcUtils;
    ​
    import java.sql.Connection;
    import java.sql.ResultSet;
    import java.sql.Statement;
    ​
    public class Test2 {
        public static void main(String[] args) throws Exception {
            Connection connection=null;
            Statement statement=null;
            ResultSet resultSet=null;
            try {
                connection= JdbcUtils.getConnection();
                statement=connection.createStatement();
                String sql="insert into users(id,name,password,email,birthday)" +
                        "values(100,'tzt','123456','123456@qq.com','1998-08-08');";
                int i=statement.executeUpdate(sql);
                if (i>0){
                    System.out.println("插入成功!");
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                JdbcUtils.release(connection,statement,resultSet);
            }
        }
    }
    

      

3、 SQL注入的问题

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

sql存在漏洞,会被攻击导致数据泄露 比如登录业务中,需要查询账号密码所对应的用户(比对),可能用到如下sql语句:

select * from users where name='name' and password ='password'

其中name和password两个变量都是用户所传入的数据 如果用户构造合适的输入,比如:

String name=" ' or  1=1 -- ";
String password ="12412r1";//password在此例中的值不重要

那么如上sql语句拼接成了:

select * from users where name='  ' or  1=1 -- password ='12412r1'

就可以匹配到表中所有用户的信息

 

4、PreparedStatement

可以防止SQL注入,而且效率更高

  • 查询

    //查询
    public class JdbcSelect {
        public static void main(String[] args) {
            Connection connection = null;
            PreparedStatement st = null;
            ResultSet rs = null;
    ​
            try {
                //获取连接
                connection= JdbcUtils.getConnection();
                //?占位符
                String sql = "select * from users where id=?";
                //预编译SQL,和Statement的区别!!!
                st = connection.prepareStatement(sql);
                //手动给参数赋值
                st.setInt(1,1);
                //执行查询
                rs= st.executeQuery();
    ​
                while (rs.next())
                    System.out.println(rs.getString("name"));
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                try {
                    JdbcUtils.release(connection,st,rs);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

      

     

  • 新增

    //新增
    public class JdbcInsert {
        public static void main(String[] args) throws SQLException {
            Connection connection=null;
            PreparedStatement st=null;
            ResultSet rs = null;
            try {
                connection = JdbcUtils.getConnection();
                String sql ="insert into users(id,name,password,email,birthday) values(?,?,?,?,?);";
                //预编译sql
                st = connection.prepareStatement(sql);
                //给参数赋值
                st.setInt(1,4);
                st.setString(2,"lolo");
                st.setString(3,"lolo666");
                st.setString(4,"lolo@qqq.com");
                st.setDate(5,new Date(new java.util.Date().getTime()));
                //执行
                int i = st.executeUpdate();
                if (i>0)
                    System.out.println("插入成功!");
    ​
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(connection,st,rs);
            }
        }
    

      

     

  • 修改

    //修改
    public class JdbcUpdate {
        public static void main(String[] args) throws SQLException {
            Connection connection=null;
            PreparedStatement st=null;
            ResultSet rs = null;
            try {
                connection = JdbcUtils.getConnection();
                String sql ="update users set `name`=?,`password`=? where id=?";
                //预编译sql
                st = connection.prepareStatement(sql);
    ​
                //给参数赋值
                st.setString(1,"jk");
                st.setString(2,"jk666");
                st.setInt(3,3);
    ​
                //执行
                int i = st.executeUpdate();
                if (i>0)
                    System.out.println("修改成功!");
    ​
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(connection,st,rs);
            }
        }
    }
     
    

      

  • 删除

    //删除
    public class JdbcDelete {
        public static void main(String[] args) throws SQLException {
            Connection connection=null;
            PreparedStatement st=null;
            ResultSet rs = null;
            try {
                connection = JdbcUtils.getConnection();
                String sql ="delete from users where id = ?";
                //预编译sql
                st = connection.prepareStatement(sql);
    ​
                //给参数赋值
                st.setInt(1,2);
    ​
                //执行
                int i = st.executeUpdate();
                if (i>0)
                    System.out.println("删除成功!");
    ​
            } catch (SQLException e) {
                e.printStackTrace();
            }finally {
                JdbcUtils.release(connection,st,rs);
            }
        }
    }
    

      

     

     

    5、IDEA连接数据库时区错误bug

    1、进入命令窗口(Win + R),连接数据库

    mysql -hlocalhost -uroot -p

    回车,输入密码,回车,

    2,继续输入

    show variables like'%time_zone';   

    (注意不要漏掉后面的分号),回车,

    显示 SYSTEM 就是没有设置时区啦。

    3,现在我们来设置时区。

    输入

    set global time_zone = '+8:00'; 

    注意不要漏掉后面的分号),回车。

 

6、事务

事务

要么都成功,要么都失败!

ACID原则:保证数据的安全。

开启事务
事务提交 commit()
事务回滚 rollback()
关闭事务

转账:
A:1000
B:1000
   
A(900)   --100-->   B(1100)

搭建一个环境

CREATE TABLE account(
   id INT PRIMARY KEY AUTO_INCREMENT,
   `name` VARCHAR(40),
   money FLOAT
);
​
INSERT INTO account(`name`,money) VALUES('A',1000);
INSERT INTO account(`name`,money) VALUES('B',1000);
INSERT INTO account(`name`,money) VALUES('C',1000);

  

  
 @Test
    public void test() {
        //配置信息
        //useUnicode=true&characterEncoding=utf-8 解决中文乱码
        String url="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf-8";
        String username = "root";
        String password = "123456";
​
        Connection connection = null;
​
        //1.加载驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2.连接数据库,代表数据库
             connection = DriverManager.getConnection(url, username, password);
​
            //3.通知数据库开启事务,false 开启
            connection.setAutoCommit(false);
​
            String sql = "update account set money = money-100 where name = 'A'";
            connection.prepareStatement(sql).executeUpdate();
​
            //制造错误
            //int i = 1/0;
​
            String sql2 = "update account set money = money+100 where name = 'B'";
            connection.prepareStatement(sql2).executeUpdate();
​
            connection.commit();//以上两条SQL都执行成功了,就提交事务!
            System.out.println("success");
        } catch (Exception e) {
            try {
                //如果出现异常,就通知数据库回滚事务
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

  

 

7、数据库连接池

数据库链接–执行完毕–施放十分消耗资源 池化技术:准备一些预先的资源,过来就链接预先准备好的

若常用连接数10个 最小连接数:10个即可 最大连接数:15 业务最高承载上限,超过此值则排队等待 等待超时:等待时间超过一定值直接失败

编写连接池:实现DataSource接口

开源数据源实现

DBCP C3P0 Druid:阿里巴巴

使用了数据库连接池之后,我们在项目开发中就不需要编写链接数据库的代码了!

  • DBCP

    • 配置文件

      driverClassName=com.mysql.jdbc.Driver
      url=jdbc:mysql://localhost:3306/jdbcstudy?useSSL=false&useUnicode=true&characterEncoding=utf8
      username=root
      password=root
    • 工具类
      • package utils;
        ​
        import org.apache.commons.dbcp.BasicDataSourceFactory;
        ​
        import javax.sql.DataSource;
        import java.io.InputStream;
        import java.sql.*;
        import java.util.Properties;
        ​
        public class JdbcUtils_DBCP {
            private static DataSource dataSource=null;
        ​
            static {
                try {
                    InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
                    Properties properties=new Properties();
                    assert in != null;
                    properties.load(in);
        ​
                    //创建数据源 工厂模式→创建
                    dataSource=BasicDataSourceFactory.createDataSource(properties);
        ​
        ​
        ​
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        ​
            //获取连接
            public static Connection getConnection() throws Exception {
                return dataSource.getConnection();
            }
        ​
            //施放资源
            public  static void release(Connection connection, Statement statement, ResultSet resultSet) throws Exception {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            }
        }
        

          


      • 测试
        • import utils.JdbcUtils_DBCP;
          ​
          import java.sql.Connection;
          import java.sql.Date;
          import java.sql.PreparedStatement;
          import java.sql.ResultSet;
          ​
          public class Test4 {
              public static void main(String[] args) throws Exception {
                  Connection connection=null;
                  PreparedStatement statement=null;
                  ResultSet resultSet=null;
                  try {
                      connection= JdbcUtils_DBCP.getConnection();
                      //?占位符
                      String sql="insert into users(id,name,password,email,birthday)" +
                              "values(?,?,?,?,?);";
                      //和Statement的区别!!!!!!!!!
                      statement=connection.prepareStatement(sql);
                      //手动给参数赋值
                      statement.setInt(1,49);
                      statement.setString(2,"few");
                      statement.setString(3,"12312313");
                      statement.setString(4,"15612318@qq.com");
                      statement.setDate(5,new java.sql.Date(new Date(1231).getTime()));
                      int i=statement.executeUpdate();
                      if (i>0){
                          System.out.println("插入成功!");
                      }
                  }catch (Exception e){
                      e.printStackTrace();
                  }finally {
                      JdbcUtils_DBCP.release(connection,statement,resultSet);
                  }
              }
          }
          

            

posted @ 2020-07-12 15:29  罗一天  阅读(213)  评论(0)    收藏  举报