10.1(java学习笔记)JDBC基本操作(连接,执行SQL语句,获取结果集)
一、JDBC
JDBC的全称是java database connection java数据库连接。
在java中需要对数据库进行一系列的操作,这时就需要使用JDBC。
sun公司制定了关于数据库操作的组接口,数据库厂商需要按照这个接口编写对应的实现类。
数据库厂商编写的实现类就称为数据库驱动。
java访问数据库流程:
1.加载驱动:加载数据库厂商提供的实现类。
2.建立连接:建立程序与数据库的连接
3.SQL语句:执行相应SQL语句
4.结果集:得到查询结果。
二、JDBC访问数据库
为了便于查看和操作数据库可以下载数据库可视化软件(例如Navicat)。
2.1准备工作:
2.1.1 下载驱动
首先我们需要下载数据库厂商提供的JDBC驱动。
2.1.2 导入驱动
由于这些驱动是数据库厂商实现的,并不在java本身的库中,所以需要从外部导入到项目中。
鼠标右击项目名称--->Bulid Path-->Configure Build Path... --> Libraries --> Add External JARs...
-->-->-->
然后找到下载的JDBC驱动所在文件夹,选择里面的mysql-connector-java-x.x.xx.jar,然后点击OK即可。
添加完毕后项目显示添加的驱动。
2.2加载驱动
public class TestJDBC{
public static void main(String[] args){
try {
//加载驱动
System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
//调用froName("x")会初始化名为x的类
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
class com.mysql.cj.jdbc.Driver
这样就代表驱动已经加载好了,这里的“com.mysql.cj.jdbc”根据下载的JDBC版本不同可能会略有不同。
一开始我写的是com.mysql.jdbc,运行后控制台提示:
Loading class `com.mysql.jdbc.Driver'.
This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'.
后来修改为com.mysql.cj.jdbc.Driver就没有问题了,这个在网上查下就可以解决了。
2.3建立连接:建立程序与数据库的连接
建立数据库连接首先我们需要了解一个类:DriverManager。
DriverManager:管理JDBC驱动的基本服务,作用于用户和驱动程序之间。
追踪可用的驱动程序,并在数据库和相关的驱动程序之间建立连接。
主要方法:
public static Connection getConnection(String url,String user, String password);
//根据给定的url地址,尝试建立数据库连接。返回一个Connection对象。
//user,password为用户名和密码。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException; public class TestJDBC{
public static void main(String[] args){
final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
String userName = "root";
String passWord = "123456";
try {
//加载驱动
System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
//调用froName("x")会初始化名为x的类 } catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行后没有报错,代表基本的连接没有问题,报错的原因有很多,一般是url格式错误,或用户名密码错误。
2.4SQL语句:执行相应SQL语句
本例所用表结构: (数据库名:mybatis,表名:tadd)
CREATE TABLE `tadd` (
`id` varchar(50) NOT NULL,
`tname` varchar(50) DEFAULT NULL,
`tpwd` varchar(50) DEFAULT NULL,
`tstudentnum` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
上面通过getConnection()建立了连接,并且返回了一个Connection对象。
我们来看下Connection对象的作用及方法。
Connection:代表了一个与指定数据库的连接,执行SQL语句返回并在连接上下文中返回结果。
主要方法:
Statement createStatement();//创建将SQL语句发送到数据库的语句对象。
PreparedStatement(String sql);//创建PreparedStatement对象。
2.4.1 Statement
Statement:主要用于执行静态的SQL语句,并返回其生成的结果对象。
主要方法:
boolean execute(String sql);执行给定的sql语句,可能返回多个结果。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement; public class TestJDBC{
public static void main(String[] args){
final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
String userName = "root";
String passWord = "123456";
try {
//加载驱动
System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
Statement sta = conn.createStatement();
boolean b = sta.execute("INSERT INTO `mybatis`.`tadd`"
+ "(`id`, `tname`, `tpwd`, `tstudentnum`) "
+ "VALUES ('17', '17', '77', '777');"); System.out.println("执行成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
class com.mysql.cj.jdbc.Driver
执行成功
我们使用可视化软件查看,发现对应数据库(mybatis)中,对应的表(tadd)里面添加了一条记录。
Statement有个缺点,不能防止SQL注入。
例如:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement; public class TestJDBC{
public static void main(String[] args){
final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
String userName = "root";
String passWord = "123456";
try {
//加载驱动
System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
//建立连接
Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
// Statement sta = conn.createStatement();
String sql = "delete from tadd where id = 1 or 1=1";
Statement ps = conn.createStatement();//创建Statement对象
ps.execute(sql);//执行SQL语句
System.out.println("执行成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
class com.mysql.cj.jdbc.Driver
执行成功
使用可视化软件我们可以看到整个表的信息都被删除了。
这时因为 where id = 1 or 1=1,关键就在后面的or 1=1,在满足id = 1 或者 1=1的条件下删除。
可1=1恒成立,加上两者又是or的关系,所以所有信息都满足删除都被删除了。
2.4.2PreparedStatement
上面我们是使用Statments来执行SQL语句,但它存在一定的缺点。
这时我们可以使用PreparedStatement,它可以防止SQL注入。
PreparedStatement:表示预编译SQL语句的对象。
SQL语句预编译并存储在PreparedStatement对象中。然后可以使用此对象多次高效地执行此语句。
继承自Statement接口,用于发送一个或多个待输入参数的sql语句。
主要方法:
void setObject(int parameterIndex, Object x);//给指定的参数索引设置指定对象x。
使用Oject的话不用在意参数类型,比较方便。
除了Object作为参数类型外,还有一些设置具体类型的函数。
void setNString(int parameterIndex, String value);给指定的参数索引设置指定的String类型的值。
void setInt(int parameterIndex, int x);给指定的参数索引设置指定的int类型的值。
void setXXX..(int parameterIndex, XXX x);设置对应类型的值,此处就不一一举例了,详见API。
此处的参数索引代表占位符的位序,具体含义详见下列代码注释。
boolean execute();执行SQL语句
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException; public class TestJDBC{
public static void main(String[] args){
final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
String userName = "root";
String passWord = "123456";
try {
//加载驱动
System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
// Statement sta = conn.createStatement();
String sql = "INSERT INTO `mybatis`.`tadd`"
+ "(`id`, `tname`, `tpwd`, `tstudentnum`) "
+ "VALUES (?, ?, ?, ?)";//?代表占位符, parameterIndex分别为1,2,3,4
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, "p1");//此处的1代表第一个占位符,即sql语句中第一个问号
ps.setObject(2, "p2");//第二个占位符,后面参数代表该占位符所代表的值
ps.setObject(3, "p3");//可用setNString(3,"p3")代替
ps.setObject(4, "p4");
ps.execute();//执行sql语句
System.out.println("执行成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
class com.mysql.cj.jdbc.Driver
执行成功
可以将sql语句设置为 delete from tadd where id = ?
再将?设置为 1 or 1= 1,可以发现表中数据并没有被全部删除。
2.5结果集:得到查询结果。
boolean excute();返回类型是布尔,如果执行SQL语句返回的是结果集则为true,其他防护false;
一般select语句才会返回结果集,所以执行select语句execute()返回true.其余语句一般为false.
excuteQuery();返回结果集,主要用于运行select语句。
excuteUpdata():返回改变的行数,主要用于insert,update,delete语句。
我们可以根据我们执行的语句,选择合适的方法得到对应的返回值。
Resultset:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
主要方法:
boolean next();//将游标移动一行,判断当前移动后的一行是否有数据。
例如,返回的结果集有,3行(编号依次为1,2,3),游标初始值为0,
调用next()方法后移动到第一行,如果第一行有数据返回true,反之返回false.
String getString(int columnLabel);//将当前行中指定列的内容转换为字符串形式。
注意这里的列从1开始计数,即数据库表中第一列数字为1,第二列数字为2.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class TestJDBC{
public static void main(String[] args){
final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
String userName = "root";
String passWord = "123456";
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
// Statement sta = conn.createStatement();
String sql = "select * from tadd where id = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1,"p1");
ResultSet rs = ps.executeQuery();//返回一个结果集对象
while(rs.next()){//判断是否有数据
System.out.println("查询结果:" +//获取对应列数据
rs.getString(1) + "---" +
rs.getString(2) + "---" +
rs.getString(3) + "---" +
rs.getString(4));
}
System.out.println("执行成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果:
查询结果:p1---p2---p3---p4
执行成功
数据库查询完毕后要将创建的各个对象依次关闭,一般是先创立的后关闭。
以上述代码为例,关闭顺序应该是Resultset-->PreparedStatement-->Connection.
关闭时最好为每一个对象添加一个try catch语句,不要将三个对象的关闭放在一个try catch中,
避免关闭其中一个出现异常时,导致其它对象没有关闭。
三、批处理
当我们需要大量(比如上万条)执行某一语句时,建议采用批处理这样可以提高执行效率。
由于PreparedStatement预编译空间有限,当数据量较大时可能出现异常,所以建议使用Statement。
基本操作和之前的没有太大区别,只是使用了几个方法。
setAutoCommit(boolean autoCommit);设置自动提交,默认为true即自动提交,false不自动提交。
addBatch(String sql);添加处理语句到批中。
excuteBatch();提交批。
commit();手动提交
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; public class TestJDBC{
public static void main(String[] args){
final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
String userName = "root";
String passWord = "123456";
Connection conn = null;
Statement ps = null;
ResultSet rs = null;
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//建立连接
conn = DriverManager.getConnection(connectionUrl,userName,passWord);
conn.setAutoCommit(false);//将自动提交设为false,即不进行自动提交
String sql = "select * from tadd where id = ?";
ps = conn.createStatement();
//批处理
for(int i = 0; i < 10000; i++){
ps.addBatch("INSERT INTO `mybatis`.`tadd`"
+ "(`id`, `tname`, `tpwd`, `tstudentnum`) "
+ "VALUES ('"+i+"', 'p1', 'p2', 'p3');");
}
ps.executeBatch();
conn.commit();//手动提交 System.out.println("执行成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//依次关闭连接
try {
rs.close();
} catch (Exception e) {
// TODO: handle exception
}
try{
ps.close();
}catch(Exception e){ }
try{
conn.close();
}catch(Exception e){
}
}
}
}
运行结果:
执行成功
查看数据库可以看到添加了10000条数据。
批处理就相当于将一个批次的语句打包一起执行,这样比一条一条单独执行效率要高。
10.1(java学习笔记)JDBC基本操作(连接,执行SQL语句,获取结果集)的更多相关文章
- QtSQL学习笔记(3)- 执行SQL语句
QSqlQuery类提供了一个用于执行SQL语句和浏览查询的结果集的接口. QSqlQueryModel和QSqlTableModel类提供了一个用于访问数据库的高级接口,这将在下一节介绍.如果你不熟 ...
- Java学习笔记--JDBC数据库的使用
参考 hu_shengyang的专栏 : http://blog.csdn.net/hu_shengyang/article/details/6290029 一. JDBC API中提供的常用数据库 ...
- Java学习笔记——JDBC之PreparedStatement类中“预编译”的综合应用
预编译 SQL 语句被预编译并存储在 PreparedStatement 对象中.然后可以使用此对象多次高效地执行该语句. 预编译的优点 1.PreparedStatement是预编译的,对于批量处理 ...
- Java学习笔记——JDBC之与数据库MySQL的连接以及增删改查等操作
必须的准备工作 一.MySQL的安装.可以参考博文: http://blog.csdn.net/jueblog/article/details/9499245 二.下载 jdbc 驱动.可以从在官网上 ...
- JAVA学习笔记 -- JDBC及其应用
一个.准备工作 1.开放SQL Server服务与支持TCP/IP 进一步确认TCPport watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjk ...
- SQLServer 学习笔记之超详细基础SQL语句 Part 10
Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 9------------------- 删除约束的语法 ALTER T ...
- SQLServer 学习笔记之超详细基础SQL语句 Part 3
Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 2------------------- 13. 使用compute对查 ...
- SQLServer 学习笔记之超详细基础SQL语句 Part 9
Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 8------------------- 3 范式的概念 第一范式的目标 ...
- SQLServer 学习笔记之超详细基础SQL语句 Part 7
Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 6------------------- 29 存储过程和触发器 存储过 ...
- SQLServer 学习笔记之超详细基础SQL语句 Part 4
Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 3------------------- 17 带比较运算符的嵌套查询 ...
随机推荐
- linux之scp命令
linux之cp/scp命令+scp命令详解 名称:cp 使用权限:所有使用者 使用方式: cp [options] source dest cp [options] source... dire ...
- TOM的show_space
show_space查看对像数据块的空闲情况 CREATE OR REPLACE PROCEDURE show_space(p_segname IN VARCHAR2, p_owner IN VARC ...
- hdu 6223 Infinite Fraction Path
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6223 题意:给定长度为n的一串数字S,现在要按照一种规则寻找长度为n的数字串,使得该数字串的字典序最大 ...
- Spring学习之路——单例模式和多例模式
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例) singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实 ...
- JVM 性能排查--汇总
参考:http://blog.sina.com.cn/s/blog_61d758500102wnus.html
- codechef T3 计算器
CALC: 计算器题目描述 大厨有一个计算器,计算器上有两个屏幕和两个按钮.初始时每个屏幕上显示的都是 0.没按 一次第一个按钮,就会让第一个屏幕上显示的数字加 1,同时消耗 1 单位的能量. 每按一 ...
- android View实现变暗效果
android项目中做一个默认图片变暗,有焦点时变亮的效果.相信大家都能各种办法,各种手段很容易的实现这个效果.这里记录下作者实现这个效果的过程及遇到的问题,仅供参考.见下图(注:因为是eclipse ...
- bzoj 1303 杂题
首先如果一个数是中位数,在这段区间中比他大的数量=比他小的数量,那么如果一个数比他大设为1,比他小设为-1,设要求的数在数组中的位置是mid,那么我们可以用num[i] 表示1-mid这一段中,j-m ...
- A trick in Exploit Dev
学习Linux BOF的时候,看了这个文章,https://sploitfun.wordpress.com/2015/06/23/integer-overflow/ ,原文给出的exp无法成功, 此时 ...
- 转:SWT中的Display 对象和 Shell对象
转自: http://blog.csdn.net/chulaixi/article/details/3095478 我们书写swt程序的步骤,这些步骤是: 1. 创建一个Display对象 2. 创建 ...