JavaEE-JDBC基础

一.JDBC和数据库驱动

JDBC(Java Database connectivity): 由java提供,用于访问数据库的统一API接口规范.
数据库驱动: 由各个数据库厂商提供,用于访问数据库的jar包(JDBC的具体实现),遵循JDBC接口,以便java程序员使用!

二.JDBC快速入门

JDBC接口类
    DriverManager 注册驱动,获取数据库连接Connection
    Connection    数据库连接,获取传输器Statement
    Statement     传输器执行sql语句
    ResultSet     查询结果集合

1.注册数据库驱动

首先,导入数据库驱动jar包(以MySQL为例,mysql-connector-java-5.1.40-bin.jar),然后注册驱动

// 方法一.导致MySql驱动被注册两次,还导致程序和具体驱动类绑定,切换数据库,需要修改java源码重新编译,不建议使用!
DriverManager.registerDriver(new Driver());

// 方法二.驱动类的静态代码块已经注册驱动,只需要加载驱动类即可
// 用反射加载,与驱动类字符串绑定,字符串可放在配置文件,切换数据库,无需改源码重新编译,只需要修改配置文件!    
Class.forName("com.mysql.jdbc.Driver");

2.建立数据库连接

Connection connection = DriverManager.getConnection(url,user,password); 
    
url格式
    MySql:      jdbc:mysql://ip:3306/sid  (本机地址简写jdbc:mysql:///sid)
    Oracle:     jdbc:oracle:thin:@ip:1521:sid
    SqlServer:  jdbc:microsoft:sqlserver://ip:1433;DatabaseName=sid
    
参数(可选,user和password可以写在url参数中)
    ?user=lioil&password=***&useUnicode=true&characterEncoding=UTF-8
    
协议:子协议://ip地址:端口号/库名?参数1=值&参数2=值
jdbc:mysql://localhost:3306/sid?useUnicode=true&characterEncoding=utf-8

3.创建Statement执行SQL

1.Statement常用方法:
    单个执行SQL语句
    boolean execute(String sql)         执行SQL语句,没有结果集返回false,有返回true(通过Statement.getResultSet获取结果集);
    ResultSet executeQuery(String sql)  执行select语句,返回结果集
    int executeUpdate(String sql)       执行insert delete update语句,返回影响行数
    
    批量执行SQL语句(insert update delete)
    void addBatch(String sql)           批量添加SQL语句(insert update delete)
    int[] executeBatch()                批量传输SQL到数据库执行,返回每个SQL语句影响行数(数组)
    void clearBatch()                   清空SQL

3.单个执行SQL语句
    // 方法一.Statement
    Statement statement = connection.createStatement();
    int row = statement.executeUpdate(sql);
    ResultSet resultSet = statement.executeQuery(sql);
    
    ResultSet默认不能反向修改数据库记录,但可通过指定参数Statement来创建可改数据的ResultSet,不建议使用,应该用update语句修改数据!!!      
        Statement state = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_UPDATABLE);       
        ResultSet resultSet = state.executeQuery("select * from user");     
        resultSet.next();       
        resultSet.updateString("name", "lioil");        
        resultSet.updateRow();
        
        Statement createStatement(int resultSetType, int resultSetConcurrency)  
        resultSetType 结果集类型   
            ResultSet.TYPE_FORWARD_ONLY        不支持滚动,只能向前.
            ResultSet.TYPE_SCROLL_INSENSITIVE  支持滚动,迟钝不敏感
            ResultSet.TYPE_SCROLL_SENSITIVE    支持滚动,敏感          
        resultSetConcurrency 是否支持修改类型
            ResultSet.CONCUR_READ_ONLY   不支持修改
            ResultSet.CONCUR_UPDATABLE   支持修改

    // 方法二.PrepareStatement预编译防止SQL注入攻击,用户参数?只做参数,不参与编译,传入SQL关键字无用
    PrepareStatement statement = connection.prepareStatement("SELECT * FROM user WHERE name=? AND password=?");
    statement.setString(1, "lioil");
    statement.setString(2, "12345");    
    ResultSet resultSet = statement.executeQuery();
    
    statement.setInt(...);
    statement.setDouble(...);
    statement.setDate(...);
    
    SQL注入:用户恶意传入一些SQL特殊关键字,导致SQL语义变化
    SELECT * FROM user WHERE name='lioil' AND password='12345';          -- 正常  
    SELECT * FROM user WHERE name='lioil' OR 1=1; --' AND password='1';  -- 恶意注入'lioil' OR 1=1; --' 使语句在OR 1=1;处结束,password没有执行

4.批量执行SQL
Statement批处理        
    Statement smt = conn.createStatement();
    smt.addBatch(sql1);
    smt.addBatch(sql2);
    smt.addBatch(sql3); 
    smt.executeBatch();
    
    优点:可执行多条不同结构SQL语句
    缺点:没预编译,效率低
    
PrparedStatement批处理     
    PrepareStatement preSmt = conn.prepareStatement("insert into user values(null,?)");         
    for(int i=1;i<=100000;i++){
        preSmt.setString(1,"id_"+i);
        preSmt.addBatch();      
        // 1000条为一批次, 减少内存占用
        if(i%1000==0){
            preSmt.executeBatch();
            preSmt.clearBatch();
        }
    }
    preSmt.executeBatch();
    
    优点:SQL结构相同,只编译一次,效率高
    缺点:只能执行相同结构SQL语句

4.结果集ResultSet(在内存以表结构形式存在)

1.移动结果集的指针/游标/当前行:
    boolean next()            移到下一行, 这行有数据返回true, 无返回false
    boolean Previous()        移到前一行
    boolean absolute(int row) 移到指定行 
    boolean first()           移到首行
    boolean last()            移到尾行
    void beforeFirst()        移到首行前一行
    void afterLast()          移到尾行后一行
    
2.获取数据
    String getString(int cloumnCount)   根据列索引,从当前行中获得String 类型数据
    String getString(String columnName) 根据列名,从当前行中获得String类型数据
    String getInt(...)
    String getLong(...)
    String getFloat/getDouble(...)
    String getDate(...)
    
实例:
    while(resultSet.next()){
        String val2 = resultSet.getString(2);
        Float val3 = resultSet.getFloat(3);
        Date val4 = resultSet.getDate(4);
        ...
    }

5.释放资源

数据库的connection个数有限,用完立即释放; 而statement和resultSet占用内存,也要释放;
释放顺序: 后创建的,先释放!
try{
    //JDBC代码...
}catch (Exception e) {
    e.printStackTrace();
}finally{
    if(resultSet != null){
        try{
            resultSet.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally{
            resultSet = null;
        }
    }
    if(statement != null){
        try {
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally{
            statement = null;
        }
    }
    if(connection != null){
        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally{
            connection = null;
        }
    }
}

三.大文本和大二进制文件(不常用)

1.大文本
    Text(Clob): TINYTEXT(255), TEXT(64k), MEDIUMTEXT(16M), LONGTEXT(4G)
    
    //建表
    create table txtTable(
        name CHAR(10),
        txt LONGTEXT
    )
        
    //插入
    File txtFile = new File("lioil.txt");
    PrepareStatement preSmt = conn.prepareStatement("insert into txtTable values(?,?)");
    preSmt.setString(1, "文本");      
    preSmt.setCharacterStream(2, new FileReader(txtFile), (int) txtFile.length());
        
    //查询
    Reader rd = resultSet.getCharacterStream("txt");
        
2.大二进制(多媒体文件)
    Blob: TINYBLOB(255), BLOB(64k), MEDIUMBLOB(16M), LONGBLOB(4G)
    
    //建表
    create table mp4Table(
        name CHAR(10),
        mp4 LONGBLOB
    )
        
    //插入
    File mp4File = new File("lioil.mp4");
    PrepareStatement preSmt = conn.prepareStatement("insert into mp4Table values(?,?)");
    preSmt.setString(1, "视频");      
    preSmt.setBinaryStream(2, new FileInputStream(mp4File), (int) mp4File.length());
        
    //查询
    InputStream in = resultSet.getBinaryStream("mp4");

简书: http://www.jianshu.com/p/ed1a59750127
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/54746135
GitHub博客:http://lioil.win/2017/01/26/JDBC.html
Coding博客:http://c.lioil.win/2017/01/26/JDBC.html

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

推荐阅读更多精彩内容

  • 1.数据库元数据(DatabaseMetaData) 2.参数元数据(ParameterMetaData) 3.结...
    lioilwin阅读 342评论 0 0
  • 1.编写连接池 2.开源数据库连接池 ①.DBCP数据源 ②.C3P0数据源 ③.tomcat内置数据源(DBCP...
    lioilwin阅读 322评论 0 0
  • 1.事务概念 2.管理事务 3.事务隔离性(多线程) 4.更新丢失 简书: http://www.jianshu....
    lioilwin阅读 251评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 西红柿炒鸡蛋,西红柿炒番茄,番茄炒西红柿,番茄炒鸡蛋。 可惜我都不会做。现在的女孩子不会做饭很丢人吗?应该不丢人...
    大脸妹妹820阅读 237评论 0 1