[19/05/06-星期一] JDBC(Java DataBase Connectivity,java数据库连接)_基本知识

一、概念

      JDBC(Java Database Connectivity)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成。是java程序与数据库系统通信的标准API。

JDBC API 使得开发人员可以使用纯java的方式来连接数据库,并执行操作。sun公司由于不知道各个主流商用数据库的程序代码,因此无法自己写代码连接各个数据库,

因此,sun公司决定,自己提供一套api,凡是数据库想与Java进行连接的,数据库厂商自己必须实现JDBC这套接口。而数据库厂商的JDBC实现,称为数据库的数据库驱动

 

JDBC驱动程序由各个数据库厂商提供,如mysql的驱动程序

二、JDBC接口

(1)Driver接口

– Driver接口由数据库厂家提供,对于java开发者而言,只需要使用Driver接口就可以了。

– 在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序。不同的数据库有不同的装载方法。

– 驱动:就是各个数据库厂商实现的Sun公司提出的JDBC接口。 即对Connection等接口的实现类的jar文件

– 装载MySql驱动  Class.forName("com.mysql.jdbc.Driver");

– 装载Oracle驱动  Class.forName("oracle.jdbc.driver.OracleDriver");

(2)DriverManager接口

– DriverManager是JDBC的管理层,作用于用户和驱动程序之间。

– DriverManager跟踪可用的驱动程序,并在数据库和相应的驱动程序之间建立连接。

(3)Connection接口

– Connection与特定数据库的连接(会话),在连接上下文中执行 SQL语句并返回结果。

– DriverManager的getConnection()方法建立在JDBC URL中定义的数据库Connection连接上

– 连接MYSQL数据库:Connection con =DriverManager.getConnection("jdbc:mysql://host:port/database","user","password");

– 连接ORACLE数据库:Connection con =DriverManager.getConnection("jdbc:oracle:thin:@host:port:databse","user","password");

(4)Statement接口

– 用于执行静态 SQL 语句并返回它所生成结果的对象。

 三种Statement类:

• Statement:由createStatement创建,用于发送简单的SQL语句。(不带参数的)

• PreparedStatement:继承自Statement接口,由prepareStatement创建,用于发送含有一个或多个输入参数的sql语句。PreparedStatement对象比Statement对象的效率更

                                     高,并且可以防止SQL注入。我们一般都用PreparedStatement.

• CallableStatement:继承自PreparedStatement 。由方法prePareCall创建,用于调用存储过程。

常用的Statement方法:

• execute():运行语句,返回是否有结果集

• executeQuery():运行select语句,返回ResultSet结果集

• executeUpdate():运行insert/update/delete操作,返回更新的行数

(5)ResultSet接口

– Statement执行SQL语句时返回ResultSet结果集。

– ResultSet提供的检索不同类型字段的方法,常用的有:

• getString():获得在数据库里是varchar、char等数据类型的对象。

• getFloat():获得在数据库里是Float类型的对象。

• getDate():获得在数据库里面是Date类型的数据。

• getBoolean():获得在数据库里面是Boolean类型的数据

/**
 * 测试与数据库的连接
 */
package com.sxt.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;


public class Demo01 {
    public static void main(String[] args) throws Exception {
        //1、加载mysql驱动
        Class.forName("com.mysql.jdbc.Driver");//加载mysql数据库的Driver类驱动。这个类是由mysql厂商写的驱动程序的提供,非sun官方
        
        //2、建立连接。程序与数据库建立连接(是比较耗时的)。Connection是Java官方给的接口,让数据库厂商去实现它。
        //参数("jdbc:mysql://host:port/database","user","password");那台机器那个端口连接哪一个数据库,用户名,密码
        Connection coon=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
        
        //3、执行sql语句。execute:[英文]执行  Statement:声明;事务;语句. Statement是Java官方的接口
        /**Statement容易发生sql注入的危险。因为他可以采用拼接字符串的形式,参数可以从外界传进来,可能有恶意代码
         * 下面的id采用拼接字符串的形式
         * String id="5 or 1=1";  这个 or 1=1就是恶意代码,可以把数据库的所有数据删除。
         * String sqlStr="delete from t_user where id"+id;
         * 这种方式不推荐
         * */        
       /*Statement state=coon.createStatement();
        String sqlStr="insert into t_user (id,username,pwd,ragTime) values (5,'李贺',980,now())";
        state.execute(sqlStr);*/
        
        /**使用PreparedStatement提高安全性,PreparedStatement是Java官方的接口,有数据库厂商提供实现
         *?是占位符,外界只能传入符合数据库类型的数据,像or 1=1这样的恶意代码不能传入。第1个?代表只能传入一个int型数字
         *其余同理。防止sql恶意注入,提高安全
         * */
        
        String sql="insert into t_user (id,username,pwd,ragTime) values (?,?,?,now())";//?是占位符
        PreparedStatement ps=coon.prepareStatement(sql);
        ps.setObject(1, 6);//1代表第1个占位符,不是从0开始,6是id号. 等价于ps.setInt(1, 6); Object是通用类型
        ps.setObject(2, "苏轼");//2代表第2个占位符 等价于ps.setString(2, "苏轼");
        ps.setObject(3, "897");//传入时间也可采用new java.sql.Date(System.currentTimeMillis()),前提是采用占位符
        //ps.execute();
        
        //executeUpdate():运行insert/update/delete操作,返回更新的行数,是个int的值,表示受到这个sql语句影响的行数
        String sql2="select *from t_user where id>?";
        PreparedStatement ps2=coon.prepareStatement(sql2);
        ps2.setObject(1, 2);//查询id>2的记录 ,Query[英文]查询
        ResultSet rs=ps2.executeQuery();//executeQuery():运行select语句,返回ResultSet结果集
        while (rs.next()) {//1 2 3 4代表列 第l列数int型 第2和3列数String型 第4列是Date型
            System.out.println(rs.getInt(1)+"  "+rs.getString(2)+"  "+rs.getString(3)+"  "+rs.getDate(4));    
        }
        
         
        //4、关闭连接 顺序是result ->statement-> connection
        rs.close();
        ps2.close();
        ps.close();
        coon.close();
        
    }
}

 

【特别】

详细操作:灵活指定SQL语句中的变量

– PreparedStatement 对存储过程进行调用

– CallableStatement  运用事务处理

– Transaction  批处理

– Batch  对于大量的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限 当数据量特别大时,会发生异常。

/**
 * 练习批处理
 */
package com.sxt.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;


public class Demo02 {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection coon=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
        coon.setAutoCommit(false);//把事务(执行语句) 设为手动提交就是false
        
        Statement state=coon.createStatement();
        
        for (int i = 10; i < 15; i++) {//Batch:[英文]一批
            state.addBatch("insert into t_user (id,username,pwd,ragTime) values ("+i+",'李 "+i+" ',888,now())");            
        }
        
        state.executeBatch();
        
        coon.commit();
        
        
    }

}

 

三、事务

一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元!

如:往银行卡中存钱,既要向本人的银行卡数据库中增加一条记录,又要向银行系统的日志中增加一条记录。如果存钱失败,则2个数据库都失败,要么都成功增加记录

他们2个是个单元。是个整体。

 开始于:数据操纵语言(Data Manipulation Language, DML)

• 连接到数据库上,并执行一条DML语句(INSERT、UPDATE或DELETE)。

• 前一个事务结束后,又输入了另外一条DML语句。

结束于:

• 执行COMMIT或ROLLBACK语句。

• 执行一条DDL语句,例如CREATE TABLE语句;在这种情况下,会自动执行COMMIT语句。

• 执行一条DCL语句,例如GRANT语句;在这种情况下,会自动执行COMMIT语句。

• 断开与数据库的连接。

• 执行了一条DML语句,该语句却失败了;在这种情况中,会为这个无效的DML语句执行ROLLBACK语句。

事务的四大特点(ACID)

– atomicity(原子性)

• 表示一个事务内的所有操作是一个整体,要 么全部成功,要么全失败;

– consistency(一致性)

• 表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前的状态;

– isolation(隔离性)

• 事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。

      事务隔离级别从低到高:

    – 读取未提交(Read Uncommitted)

    – 读取已提交(Read Committed)

    – 可重复读(Repeatable Read)

    – 序列化(serializable)

– durability(持久性)

• 持久性事务完成之后,它对于系统的影响是永久性的。

/***
 * 测试事务
 */
package com.sxt.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;

public class Demo03 {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection coon=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
        coon.setAutoCommit(false);//默认是true 自动提交,这里是手动提交。通过设置如果ps2语句有错,即使ps1语句没错
                    //数据库也不会改变因为他们是一批事务.他们要么同时成功要么同时失败。
        
        PreparedStatement ps1=coon.prepareStatement("insert into t_user (id,username,pwd,ragTime) values (?,?,?,now())");
        ps1.setObject(1, 7);
        ps1.setObject(2, "韩愈");
        ps1.setObject(3, "667");        
        ps1.execute();
        Thread.sleep(2000);
        
        PreparedStatement ps2=coon.prepareStatement("insert into t_user (id,username,pwd,ragTime) values (?,?,?,now())");
        ps2.setObject(1, 8);
        ps2.setObject(2, "陆游");
        ps2.setObject(3, "907");        
        ps2.execute();
        
        coon.commit();
    
        
    }

}

 

四、时间类型

/***
 * 测试时间处理相关的(java.sql.Date 年月日,Time 时分秒,TimeStamp 时间戳 年与日时分秒)
 */
package com.sxt.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.util.Random;


public class Demo04 {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection coon=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
        
        PreparedStatement ps1=coon.prepareStatement("insert into t_user (id,username,pwd,ragTime) values (?,?,?,?)");
        ps1.setObject(1, 9);
        ps1.setObject(2, "曹操");
        ps1.setObject(3, "689");
        //1、测试java.sql.Date
        java.sql.Date date=new java.sql.Date(System.currentTimeMillis());
        ps1.setObject(4, date);//Date类在添加到数据库中只有年月日是没有时分秒,如果数据库采用时间戳格式则时分秒默认为00:00:00    
        //ps1.execute();
        
        //2、测试java.sql.TimeStamp 时间戳
        PreparedStatement ps2=coon.prepareStatement("insert into t_user (id,username,pwd,ragTime) values (?,?,?,?)");
        ps2.setObject(1, 10);
        ps2.setObject(2, "杜牧");
        ps2.setObject(3, "459");
        //若要插入指定日期需要使用Calendar类 或者DateFormat类
        Timestamp ts =new Timestamp(System.currentTimeMillis());
        ps2.setObject(4, ts);
        //ps2.execute();
        
        //3、测试插入随机日期
        for (int i = 15; i <= 20; i++) {
            PreparedStatement ps3=coon.prepareStatement("insert into t_user (id,username,pwd,ragTime) values (?,?,?,?)");
            ps3.setObject(1, i);
            ps3.setObject(2, "杜"+i);
            ps3.setObject(3, "999");
            
            int rand=200000+new Random().nextInt(10000000);//1000万范围的随机数+200000 
            Timestamp ts2 =new Timestamp(System.currentTimeMillis()-rand);//单位是毫秒
            ps3.setObject(4, ts2);
            ps3.execute();
        }
        
        
    }
}
/***
 * 查询指定日期的记录
 */
package com.sxt.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import javax.xml.stream.events.EndDocument;

public class Demo05 {
    
    public static long strToDate(String strDate) throws Exception {
        
        DateFormat format=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");        
        return format.parse(strDate).getTime();//把传进来的字符串改成时间格式然后获取它的时间
    }
    
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        Connection coon=DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
        
        String sql="select *from t_user where ragTime>? and ragTime<?";
        PreparedStatement ps=coon.prepareStatement(sql);
        java.sql.Timestamp start=new java.sql.Timestamp(strToDate("2019-05-10 10:00:00"));
        java.sql.Timestamp end=new java.sql.Timestamp(strToDate("2019-05-15 10:00:00"));
        
        ps.setObject(1, start);//设置第一个占位符,查询ragTime>start的记录 ,Query[英文]查询
        ps.setObject(2, end);
        ResultSet rs=ps.executeQuery();//executeQuery():运行select语句,返回ResultSet结果集
        while (rs.next()) {//1 2 3 4代表列 第l列数int型 第2和3列数String型 第4列是Date型 也可以写rs.getInt("id")等
            System.out.println(rs.getInt(1)+"  "+rs.getString(2)+"  "+rs.getString(3)+"  "+rs.getTimestamp(4));    
        }

    }

}

 

转载于:https://www.cnblogs.com/ID-qingxin/p/10823157.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值