JDBC主要编程接口对象
JDBC即java数据库互连,是java语言和数据库之间独立于数据库的连接标准API,JDBC从根本上来说是 一种规范,具体的实现需要依赖于具体数据库生产商提供jar包【驱动】,提供了统一的接口用于访问不 同的底层数据库,允许使用java语言编写不同的应用程序以访问数据库。
public class Test1 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///test?
serverTimezone=UTC", "root", "123456");
stmt = conn.createStatement();
// 执行修改操作 insert update delete, 返回值为int型表示sql语句执行时的受影响行数
// int len=stmt.executeUpdate("insert into tb_student(name)
// values('华子')");
// 执行查询操作 select 返回值为ResultSet
rs = stmt.executeQuery("select * from tb_student");
while (rs.next()) {
String dept = rs.getString("dept");
Long id = rs.getLong("id");
String name = rs.getString("name");
int age = rs.getInt("age");
Boolean sex = rs.getBoolean("sex");
System.out.println(id + "\t" + name + "\t" + age + "\t" +
sex + "\t" + dept);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
if (stmt != null)
stmt.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Connection接口
Connection接口用于表示应用程序和数据库系统之间的静态连接,提供了针对事务处理的方法以及创建 执行sql语句和存储过程的方法,同时提供了一些基本的错误处理方法
public interface Connection extends Wrapper, AutoCloseable
-
createStatement():Statement 创建用于执行sql语句的语句对象
-
prepareStatement(String sql):PreparedStatement 创建PreparedStatement对象,用于实现数据库的动态访问
-
prepareCall(String sql):CallableStatement 用于创建执行存储过程的CallableStatement对象
-
close():void结束Connection对象数据库连接,务必注意:数据库连接属于稀有资源,必须保证及时关闭
-
isClose():boolean测试是否已经关闭数据库连接
-
setAutoCommit(boolean):void设置事务是否自动提交
-
commit()在连接上提交事务
-
rollback()回滚撤销事务
Statement接口
Statement接口用于提交执行静态的SQL语句,并返回SQL的执行结果
public interface Statement extends Wrapper, AutoCloseable
-
executeQuery(String查询语句):ResultSet 执行sql语句,并返回满足查询条件的结果集
-
executeUpdate(String增删改语句):int 执行增删改语句,并返回sql语句的影响行数
-
execute(String sql):boolean 执行任意的SQL语句,如果第一个执行结果是ResultSet则会返回
true,如果返回整数则返回false
public class Test2 {
public static void main(String[] args) throws Exception {
new Driver();
try (
Connection conn =
DriverManager.getConnection("jdbc:mysql:///test?
serverTimezone=Asia/Shanghai", "root","123456");
Statement stmt = conn.createStatement();
) {
String sql = "create table if not exists tb_users(id int)";
boolean res = stmt.execute(sql);
System.out.println(res);
}
}
}
- close():void 关闭语句对象
- addBatch(String sql)将多条sql语句放入到一个批处理中执行
- executeBatch()向数据库发送一批sql语句,并执行
三种语句对象
在JDBC种提供了三种语句对象Statement、PreparedStatement和CallableStatement
- Statement用于发送简单的静态SQL语句,不带参数。不支持预编译、有sql注入的风险。不允许使 用
mysql> create table tb_users(
-> id bigint primary key auto_increment,
-> username varchar(20) not null,
-> password varchar(20) not null);
Query OK, 0 rows affected (0.03 sec)
//所谓的用户登录就是提交用户名称和口令到应用中,应用按照用户名username和口令password,到数据库tb_users表中进行查询,如果能够查询到数据,则登录成功,否则登录失败
String username = "yanjun";
String password = "123456";
boolean success = false;
try (
Connection conn = DriverManager.getConnection("jdbc:mysql:///test?
serverTimezone=Asia/Shanghai", "root", "123456");
Statement stmt = conn.createStatement();
) {
// 通过字符串拼接生成对应的sql语句
String sql = "select * from tb_users where username='" + username + "'
and password='" + password + "'";
success = stmt.executeQuery(sql).next();
}
if (success)
System.out.println("登录成功!");
else
System.out.println("登录失败!");
- PreparedStatement是Statement的子接口,用于发送含有一个或者多个参数的sql语句。PreparedStatement比Statement执行效率高,因为它支持预编译功能,同时在一定程度上可以防 止SQL注意,一般使用使用这个接口
public class Test4 {
public static void main(String[] args) throws Exception {
String username = "zhangsan";
String password = "123456";
try (Connection conn =
DriverManager.getConnection("jdbc:mysql:///test?
serverTimezone=Asia/Shanghai", "root",
"123456"); ) {
String sql="select * from tb_users where username=? and
password=?";
PreparedStatement ps=conn.prepareStatement(sql);
//针对?参数ps对象提供了一组对应的setXxx方法,用于给参数赋值
ps.setString(1, username);
ps.setString(2, password);
ResultSet rs=ps.executeQuery();
while(rs.next()){
String upwd=rs.getString("password");
long id=rs.getLong("id");
String uname=rs.getString("username");
System.out.println(id+"\t"+uname+"\t"+upwd);
}
}
}
}
- CallableStatement接口继承于PreparedStatement接口,主要用于调用执行存储过程
一般在具体应用开发中不使用Statement,基本上都是使用PreparedStatement,主要原因就是
PreparedStatement具有Statement的所有功能,同时支持预编译,还有避免SQL注入风险
Statement和PreparedStatement的区别
- Statement只能处理静态SQL,PreparedStatement既能处理静态SQL,也能处理动态SQL,它继 承于Statement接口
- PreparedStatement支持预编译,所以适合执行连续多次相同结构的SQL语句,Statement不适合
SQL注入
客户端利用jdbc statement的缺点,传入非法参数,从而使jdbc返回不合法的值,通常称为sql注入
String username = "zhangsan";
String password = "12345' or '1'='1";
boolean success = false;
try (
Connection conn = DriverManager.getConnection("jdbc:mysql:///test?
serverTimezone=Asia/Shanghai", "root","123456");
Statement stmt = conn.createStatement();
) {
// 通过字符串拼接生成对应的sql语句
String sql = "select * from tb_users where username='" + username +
"' and password='" + password + "'";
System.out.println(sql);
success = stmt.executeQuery(sql).next();
}
if (success)
System.out.println("登录成功!");
else
System.out.println("登录失败!");
ResultSet接口
ResultSet接口用于得到包含了执行SQL查询结果的结果集,要获取表中任何一个字段项都要先找到该字段项所处于的行,再获取对应的列
- 获取数据要依靠一个指向当前行的指针,开始时指向满足条件的第一行之前,每次执行next方法, 则指针后移,到达目标行后就可以使用getXxx方法获取对应列的值
- boolean next()指针后移,如果有数据则返回true,否则false
- getXxx(int索引序号/String列名称):Xxx 获取对应列值
时间类型处理
java.util.Date类型用于封装日期时间【具体实现实际上保存的是从1970-1-1 0:0:0到指定时刻的毫秒值】;在java.sql中针对日期时间类型提供了3个java.util.Date类型的子类
- java.sql.Date只有日期
- java.sql.Time只有时间
- java.sql.Timestamp具有日期时间
传入日期类型数据
String sql="select * from tb_users where birth=?"; //假设birth是日期类型
PreparedStatement ps = conn.prepareStatement(sql);
//setDate方法要求参数必须是java.sql.Date类型,不能是java.util.Date类型
java.sql.Date dd=new java.sql.Date(now.getTime());//now中实际包含年月日时分秒,dd
中只有年月日
ps.setDate(1, dd);
ResultSet rs = ps.executeQuery();
接收日期类型数据
while (rs.next()) {
long id = rs.getLong("id");
java.util.Date birth=rs.getDate("birth");//rs.getDate获取的数据类型是
java.sql.Date,所以只有年月日,如果需要时分秒则使用getTime,如果需要年月日时分秒则使用
getTimestamp
System.out.println(id + "\t" + birth);
}