JDBC简明笔记 2018-03-25

假设电脑已经安装有 mySQL,并在里面有一些表。现在,我们想通过 Java,来访问数据库里的表。

JDBC (Java DataBase Connection) 指的就是通过Java访问数据库。

这是我的数据库情况。

JDBC的连接

首先到 mySQL 的官网,下载 Connectors/J 驱动,下载完解压出其中的 jar 包,放到项目的依赖里(IDEA - File - Project Structure - Modules - Dependencies - “+” 选择刚刚解压的jar文件)。

初始化驱动

在Java中,使用 Class.forName来初始化驱动(这一步在 jdk 1.6 以后已经不是必须)

建立数据库连接

建立与数据库的Connection连接,是通过 DriverManager 类的getConnection方法来实现的,因此首先要创建一个Connection实例。

1Connection c = DriverManager.getConnection(url,user,psw);

getConnection方法接收三个参数,连接地址,用户名、密码。或者接收一个参数连接地址,该连接地址里已经URL构造了用户名和密码。

连接地址需要提供:

数据库所处于的ip:127.0.0.1 (本机)

数据库的端口号: 3306 (mysql专用端口号)

数据库名称: class_info

编码方式: UTF-8

账号: root

密码: 123456

packagecom.jerrysheh;

importjava.sql.*;

publicclassgo{

publicstaticvoidmain(String[] args)throwsSQLException{

String base_url ="jdbc:mysql://127.0.0.1:3306/";

String table_name ="class_info";

String Encoding ="UTF-8";

String user ="root";

String psw ="9501";

String SSL ="false";

String url = String.format("%s%s?characterEncoding=%s&user=%s&password=%s&useSSL=%s",base_url,table_name,Encoding,user,psw,SSL);

        Connection c = DriverManager.getConnection(url,user,psw);

System.out.println("连接成功:"+ c);

    }

}

这样就与数据库连接成功了。

如果没有添加&useSSL=false, IDEA 会报一个 WARN

Tue Mar 20 18:39:15 CST 2018 WARN: Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

获取执行对象 statement

成功连接数据库以后,我们要创建一个可以对数据库进行增删查改等操作的对象,叫做statement。

1

2

// 注意,IDE提示有多个 statement,这里选择java.sql.Statement

Statement s = c.createStatement();

执行 SQL 语句

有了可以对数据库进行操作的statement后,我们就可以执行数据库语句了。

如果需要返回结果,需要用ResultSet对象。


String sql ="select * from my_table";

ResultSet rs = s.executeQuery(sql);

关于 ResultSet 的用法,可以参考Oracle官方文档

一般我们是用 rs.next()去读取

String sql ="select * from my_table";

ResultSet rs = s.executeQuery(sql);

//如果有数据,rs.next()返回true

while(rs.next()){

System.out.println(rs.getInt("stu_id") +"\t"+

rs.getString("stu_name") +"\t"+

rs.getString("stu_phone_number"));

}

rs.getInt()方法,可以接收 String 参数,列名,如上面例子所示。 也可以接收 Int 参数, 列号。 如rs.getInt(2)就是返回数据库的第二列。

rs.getInt(1) 是 Java 自带 API 里, 唯二的其中一个,1作为起始的,一般都是 0 为起始。 另一个是PreparedStatement,下面将会讲到。

输出

1 张三 13112299520

2 李四 13211012345

3 王五 13711155560

跟我的数据库表正好匹配

关闭数据连接

数据库是有限资源,使用完毕需要断开连接

s.close();

rs.close();

c.close();

可以用 java 7 的特性 try-with-resource 来自动管理连接,这样就不用每次都去手动关闭。

try(

        Connection c = DriverManager.getConnection(url,user,psw);

        Statement s = c.createStatement();           

    )

        {

String sql ="select * from my_table";

            s.execute(sql);

}catch(SQLException e) {

            e.printStackTrace();

        }

增、删、改

CRUD 是最常见的数据库操作,即增删改查

C 增加(Create)

R 读取查询(Retrieve)

U 更新(Update)

D 删除(Delete)

增加


String sql ="insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";

s.execute(sql);

删除

String sql ="delete from hero where id = 5";

s.execute(sql);

修改

String sql ="update hero set name = 'name 5' where id = 3";

s.execute(sql);

使用PreparedStatement

和 Statement 一样,PreparedStatement 也是用来执行sql语句的。其优点是,能设置参数指定相应的值,而不是Statement那样使用字符串拼接。


String sql ="insert into hero values(null,?,?,?)";

try( Connection c = DriverManager.getConnection(url,user,psw);

      PreparedStatement ps = c.prepareStatement(sql);

    ) {

// 设置参数

ps.setString(1,"je");

ps.setFloat(2,313.0f);

ps.setInt(3,50);

// 执行

            ps.execute();

}catch(SQLException e) {

            e.printStackTrace();

        }

PreparedStatement用setString(1,"je")这样的方式,来给每一个参数设置值,比如 1,”je”,就是第一个?的值设为je

为什么使用PreparedStatement

使用Statement:

1String sql ="insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";

使用PreparedStatement

1String sql ="insert into hero values(null,?,?,?)";

Statement 采用的是字符串拼接,不仅麻烦,还有被SQL注入的风险

execute 和 executeUpdate 的比较

相同点:都可以执行增加,删除,修改

不同点:

executeexecuteUpdate

可以执行查询语句,然后通过getResultSet,把结果集取出来不能执行查询语句

返回boolean,true表示执行的是查询语句,false表示执行的是insert,delete,update等类型返回int,表示有多少条数据受到了影响

获取数据表元数据


Connection c = DriverManager.getConnection(url,user,psw);

DatabaseMetaData dbmd = c.getMetaData();

//获取数据库产品名称

dbmd.getDatabaseProductName();

//获取数据库产品版本

dbmd.getDatabaseProductVersion();

//获取驱动版本

dbmd.getCatalogSeparator();

//获取可用的数据库列表

ResultSet rs = dbmd.getCatalogs();

while(rs.next()) {

System.out.println("数据库名称:\t"+rs.getString(1));

      }

使用事务

当我们对数据库进行一组操作时,假若其中一条语句有误,其他正确的语句被执行并提交到数据库了,有误的语句没有被执行,那么会导致结果不可预期。

我们希望,这组操作要么全部成功,要么全部失败。不要部分成功部分失败。

这时候可以使用事务。

用setAutoCommit(false)来关闭自动提交,这时候语句不会被提交到数据库,直至我们用commit()手动提交。


c.setAutoCommit(false);

// 加血的SQL

String sql1 ="update hero set hp = hp +1 where id = 22";

s.execute(sql1);

// 减血的SQL

// 不小心写错写成了 updata(而非update)

String sql2 ="updata hero set hp = hp -1 where id = 22";

s.execute(sql2);

// 手动提交

c.commit();

MYSQL 表的类型必须是INNODB才支持事务

使用 ORM

ORM (Object Relationship database Mapping)

意思是:对象和关系数据库的映射

简单说,一个对象,对应数据库里的一条记录

首先定义一个 student 类,根据我们的数据库表,这个类应该有三个属性: id、name、phonenumber

student.java


packagecom.jerrysheh;

publicclassstudent{

intstudent_id;

    String student_name;

longstudent_phone_number;

publicvoidsetStudent_id(intstudent_id){

this.student_id = student_id;

    }

publicvoidsetStudent_name(String student_name){

this.student_name = student_name;

    }

publicvoidsetStudent_phone_number(longstudent_phone_number){

this.student_phone_number = student_phone_number;

    }

publicStringgetStudent_name(){

returnstudent_name;

    }

}

然后在主类里,定义getStudent(),传入id,返回student

这个 getStudent() 做了什么事情呢?

他就是把数据库里查到的每一项,映射给我们 student 对象的每一个属性里去。

比如,数据库里,stu_id 为 1 的 同一行 stu_name 为 “张三”。 那getStudent()做的事情就是,把这个1映射给 student对象的 id 属性, 把 “张三” 映射给student对象的 name 属性。

这样,我们就得到一个表示数据库一行的对象实例了。

这就是ORM技术。

test.java


packagecom.jerrysheh;

importjava.sql.*;

publicclassgo{

publicstaticstudentgetStudent(intid)throwsSQLException{

String base_url ="jdbc:mysql://127.0.0.1:3306/";

String db_name ="class_info";

String Encoding ="UTF-8";

String user ="root";

String psw ="9501";

String SSL ="false";

String url = String.format("%s%s?characterEncoding=%s&user=%s&password=%s&useSSL=%s",base_url,db_name,

                Encoding,user,psw,SSL);

student s =null;

String sql ="select * from my_table";

try(

                Connection c = DriverManager.getConnection(url,user,psw);

                PreparedStatement ps = c.prepareStatement(sql);

                ResultSet rs = ps.executeQuery(sql)

        ){

//ps.setInt(1,id);

if(rs.next()){

s =newstudent();

String name = rs.getString(2);

longphone_number = Long.parseLong(rs.getString(3));

                s.setStudent_id(id);

                s.setStudent_name(name);

                s.setStudent_phone_number(phone_number);

            }

}catch(SQLException e){

            e.printStackTrace();

        }

returns;

    }

publicstaticvoidmain(String[] args)throwsSQLException{

student s = getStudent(1);

        String name = s.getStudent_name();

        System.out.println(name);

    }

}

我们在 main 里实例化了一个 student, 用 getStudent() 方法去获取一个student对象。

然后我们用getStudent_name()来验证是不是对应数据库里的”张三”。

输出:

张三

Process finished with exit code 0

果然如此!

其他ORM方法

根据ORM映射数据库和ORM的思想,我们可以设计其他几个常用的ORM方法:

把一个student对象插入到数据库中


publicstaticvoidadd(student s){

}

把一个student从数据库中删除

publicstaticvoiddelete(student s){

}

更新一个student对象的信息

publicstaticvoidupdate(student s){

}

最后,我们把所有的student数据查询出来,转换为student对象后,放在一个集合中返回

1publicstaticList list();

这样,我们的 ORM 就封装好了。

使用 DAO

DAO (DataAccess Object), 数据库访问对象

DAO其实就是把数据库相关的操作都封装在类里面,其他地方看不到JDBC的代码

publicinterfaceDAO{

//增加

publicvoidadd(Hero hero);

//修改

publicvoidupdate(Hero hero);

//删除

publicvoiddelete(intid);

//获取

publicHeroget(intid);

//查询

publicListlist();

//分页查询

publicListlist(intstart,intcount);

}

封装接口,然后设计类,实现这个接口。

这样,我们需要数据库信息时,直接通过 DAO,获取封装好的对象,我们就能直接对对象进行操作。

在 Java 中,比较常用的 ORM 框架有 Hibernate和 iBatis,我们可以直接拿来用。这样,就不用繁琐地跟 JDBC 打交道了。

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

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,631评论 18 399
  • 一. Java基础部分.................................................
    wy_sure阅读 3,811评论 0 11
  • 不管是莫名其妙刺痛心脏的疼痛,还是猝不及防从悬崖边跌落的惶恐,都只不过是无数情歌创作的中心主旨,是因为听到太...
    猫妖君阅读 262评论 0 0
  • 摄影/祈澈姑娘
    祈澈菇凉阅读 287评论 2 3
  • 不要做勤奋的表演,做好自己,做好没件事,分配好时间✔
    夜月神阅读 168评论 0 0