MySQL之JDBC(重点)

一、数据库驱动

链接数据库和应用程序的中间环节,不同的数据库会有不同的驱动,所以对于java开发者需要一个规范来统一操作数据库,这就出现了JDBC

二、JDBC

JDBC一个java数据库的规范,对于java人员只需要掌握JDBC就可以了,没有什么问题是加一层解决不了的。
JDBC中间层

我们需要java.sql和javax.sql,还需要导入一个数据库驱动包mysql-connector-java

三、第一个JDBC程序

创建测试数据库

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')

1、创建一个普通项目
2、导入数据库驱动


QQ截图20200707222827.png

3、编写测试代码

public class JdbcFirstDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动
        //2.用户信息和url
        //useUnicode=true&characterEncoding=utf8&useSSL=true
        String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String username="root";
        String password="123456";

        //3.链接成功,数据库对象,connection代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);
        //4.执行SQL的对象,去执行SQL,statement的对象
        Statement statement = connection.createStatement();

        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"));
            System.out.println("pwd="+resultSet.getObject("PASSWORD"));
            System.out.println("email="+resultSet.getObject("EMAIL"));
            System.out.println("birth="+resultSet.getObject("birthday"));
            System.out.println("=======================================");
        }
        //5.释放链接
        resultSet.close();
        statement.close();
        connection.close();
    }
}

步骤总结:
(1)加载驱动
(2)连接数据库 DriverManager
(3)获得执行sql对象 Statement
(4)获得返回的结果集
(5)释放连接

DiverManager

//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver");//固定写法,加载驱动
//connection 代表数据库
Connection connection = DriverManager.getConnection(url, username, password);

URL

String url="jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
//jdbc:mysql://主机地址:端口号/数据库名?参数1&参数2&参数3

//oracle -- 1521
//jdbc:oracle:thin:@localhost:1521:sid

Statement 执行SQL对象 PrepareStatement 执行SQL对象

statement.executeQuery();//查询返回结果 ResultSet
statement.executeUpdate();//更新,插入,删除都是这个,返回一个受影响的行数
statement.execute();//执行任何SQL

ResultSet查询结果集:封装所有查询结果

获得指定的数据类型

ResultSet resultSet = statement.executeQuery(sql);//返回结果,封装了所有我们全部查询出的结果
//不知道列类型情况下使用
resultSet.getObject();
resultSet.getInt();
resultSet.getFloat();
resultSet.getDate();

遍历

resultSet.beforeFirst();//最前面
resultSet.afterLast();//最后面
resultSet.next();//下一个
resultSet.previous();//前一个
resultSet.absolute(row);//移动到指定行

释放资源

//5.释放链接
resultSet.close();
statement.close();
connection.close();//消耗资源,用完关掉

四、statement对象

CRUD操作-insert

Statement st = connection.createStatement();
String sql="insert into user(...) values(...)";
int num=st.executeUpdate(sql);
if (num>0){
       System.out.println("插入成功!!!");
}

CRUD操作-delete

Statement st = connection.createStatement();
String sql="delete from user where id =1";
int num=st.executeUpdate(sql);
if (num>0){
       System.out.println("删除成功!!!");
}

CRUD操作-update

Statement st = connection.createStatement();
String sql="update user set name='' where name='' ";
int num=st.executeUpdate(sql);
if (num>0){
       System.out.println("修改成功!!!");
}

CRUD操作-read

Statement st = connection.createStatement();
String sql="select * from user where id=1 ";
ResultSet rs=st.executeUpdate(sql);
if (num>0){
       //根据返回的数据类型,分别调用rs的相应方法映射到java对象中
}

代码实现

1、提取工具类
2、编写增查删改,excuteUpdate/excuteQuery

//增删改
    public static void main(String[] args){
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;

        try {
            conn = JdbcUtils.getConnection();
            st=conn.createStatement();
            String sql="INSERT INTO users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)" +
                    "VALUES(4,'kuangshen','123456','543682418@qq.com','2020-01-01')";
            int n=st.executeUpdate(sql);
            if (n>0){
                System.out.println("插入成功!!!");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
//查
    public static void main(String[] args) {
        Connection conn=null;
        Statement st=null;
        ResultSet rs=null;

        try {
            conn = JdbcUtils.getConnection();
            st=conn.createStatement();

            String sql="SELECT * FROM users  WHERE id=3";
            rs=st.executeQuery(sql);

            while (rs.next()){
                System.out.println(rs.getString("id"));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }

    }

SQL注入问题

sql存在漏洞,会被攻击导致数据泄露,SQL会被拼接 or

String sql="SELECT * FROM users  WHERE `NAME`=' ' or '1=1' AND `PASSWORD`='' or '1=1'";

五、PreparedStatement对象

PreparedStatement可以防止SQL注入并且高效

    public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement st=null;
        try {
            conn=JdbcUtils.getConnection();

            //区别
            //使用?占位符代替参数
            String sql="insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`)values(?,?,?,?,?)";

            st=conn.prepareStatement(sql);//预编译sql

            //手动参数赋值
            st.setInt(1,2);
            st.setString(2,"朱飞宇");
            st.setString(3,"123456");
            st.setString(4,"3215125@qq.com");
            //注意点:sql.Date 数据库 java.sql.Date
            //       util.Date java new Date().getTime()
            st.setDate(5,new java.sql.Date(new Date().getTime()));

            //执行
            int n=st.executeUpdate();
            if (n>0){
                System.out.println("插入成功!");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,null);
        }
    }

六、IDEA连接数据库

  • Step1:连接数据库


    MySQL
  • Step2:连接成功后可以选择数据库


    选择数据库
  • Step3:双击数据库


    查看数据库
  • Step4:写SQL的地方


    QQ截图20200709193459.png

七、事务

要么都成功要么都失败

ACID 原则

原子性:要么全部完成要么都不完成
一致性:总数不变
隔离性:多个进程互不干扰
持久性:一旦提交不可逆,持久化到数据库

隔离性的问题:
脏读:一个事务读取了另一个没有提交的事务。
不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变。
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后结果不一致。

   public static void main(String[] args) {
        Connection conn=null;
        PreparedStatement st=null;
        ResultSet rs=null;

        try {
            conn=JdbcUtils.getConnection();
            //关闭数据库的自动提交,自动会开启事务
            conn.setAutoCommit(false);//开启事务
            String sql1="update account set money=money-100 where name='A'";
            st=conn.prepareStatement(sql1);
            st.executeUpdate();

            String sql2="update account set money=money+100 where name='B'";
            st=conn.prepareStatement(sql2);
            st.executeUpdate();

            //业务完毕提交事务
            conn.commit();
            System.out.println("成功!");

        } catch (SQLException throwables) {
            try {
                conn.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            throwables.printStackTrace();
        }finally {
            JdbcUtils.release(conn,st,rs);
        }
    }

八、数据库连接池

数据库连接和释放是非常浪费资源的,所以现在的池化技术主要是预先准备好资源,用完等待下一个。

  • 最小连接数:10
  • 最大连接数:100 业务最高承载上线,一旦超过就会排队等待
  • 等待超时:100ms 拒绝服务
    编写连接池只需要实现一个接口:DateSource

开源数据源实现

DBCP
C3P0
Druid
使用这些数据库连接池后,我们在项目中就不需要编写连接数据库的代码了。

DBCP

需要用到的jar包
commons-dbcp-1.4.jar
commons-pool-1.6.jar

结论

无论使用什么数据源,本质还是一样,DataSource的接口不变

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342