JDBC全称为Java Database Connectivity
,直译过来就是Java数据库连接。它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现。我们要连接数据库,就要去相应的数据库官网下载驱动,驱动都是以jar包的形式存在,jar包当中有很多.class文件,这些class文件就是JDBC接口的实现。本文针对MySQL数据库的连接实现。
数据库连接完整代码如下:
import java.sql.*;
public class JDBCTest06 {
public static void main(String[] args) {
Connection conn = null;
Statement state = null;
Driver driver = null;
ResultSet rs = null;
try {
/*
注册驱动
在此处,Driver类型的对象driver和后面的com.mysql.cj.jdbc.Driver()并不是一个,它们是不同包下的。
*/
driver = new com.mysql.cj.jdbc.Driver();
DriverManager.registerDriver(driver);
/*
第二步:获取连接
这里的url是由以下部分组成的:
协议:jdbc:mysql://
数据库服务端ip地址:因为这里使用的是本机,所以写的是localhost
数据库端口号:MySQL的专用端口号:3306
数据库账号:root
密码:111111
*/
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/study2","root","111111");
//获取数据库操作对象
state = conn.createStatement();
/*
执行sql语句
若执行DML语句(update,insert,delete),写法如下:
state.executeUpdate("insert into user (id,name) value ("1", "张三")");
下面演示的是执行DQL语句(select)
*/
rs = state.executeQuery("select *from user");
/*
处理查询结果
如果rs中还有没有访问的记录,next()方法则会返回true
如果访问的字段是varChar类型,则使用getString(),若访问字段是int类型,则使用getInt(),若访问字段是bigint,则使用getDouble(),其余同理。
注意这里getStrng()以及同类型方法的传参,可以传一个字段名,也可以传要查询字段的下标(从1开始)
*/
while(rs.next()){
System.out.println(rs.getString(1) + " " + rs.getString(2));
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
//释放资源,要从小到大释放
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(state != null){
try {
state.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
在注册驱动时,我们现在并不会这样写,因为com.mysql.cj.jdbc.Driver类的源码中有如下静态代码块:
我们在这里简单的利用数据库实现一个账号的登录。
public static boolean Login(String loginName, String passWord){
Connection conn = null;
Statement state = null;
ResultSet st = null;
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost/study2","root","111111");
//获取数据库操作对象
state = conn.createStatement();
//执行查询语句
st = state.executeQuery("select *from login where loginName ='" + loginName + "'and loginPwd = '" + passWord + "'");
if(st.next()){
return true;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally {
if (state != null) {
try {
state.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
;
}
}
return false;
}
在这里我们借助了SQL语句的拼接来实现了一个账号登录功能,其中loginName,和passWordd都是由用户来输入的。如果用户正常输入,例如:输入loginName为’‘111
’‘,输入passWord为’‘12345678
’',拼接之后的SQL语句如下:
select * form login where loginName = '111' and passWord = '12345678'
只要用户输入的名字和密码是正确的,就会有查询结果,登录成功。
如果用户在输入时输入了带有sql关键字的’非法信息’并且该非法信息串改了sql语句的原先的含义,导致未输入正确的信息也同样登录成功,例如:输入loginName为’‘111
’',输入passWord为 ‘‘1' or ' 1' = '1
’’,拼接之后的SQL语句如下:
select * from login where loginName = '111' and passWord = '1' or '1' = '1';
用户如果这样输入就改变的SQL语句的原意,导致在不知道账号密码的情况下仍然登录成功,这就是SQL注入
。
上面使用Statement对象执行sql语句会造成SQL注入问题,Statement的子类PreparedStatement对象可以预编译SQL语句,从而避免了这种问题。
使用PreparedStatement来实现一个简单的登入如下:
public static boolean login(String loginName, String passWord){
ResultSet rs = null;
Connection conn = null;
//预编译的数据库操作对象
PreparedStatement ps = null;
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//连接数据库
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/study2","root","111111");
//获取预编译的数据库操作对象
ps = conn.prepareStatement("select * from login where loginName = ? and loginPwd = ?");
//给占位符传值
ps.setString(1,map.get("loginName"));
ps.setString(2,map.get("passWord"));
//执行sql语句
rs = ps.executeQuery();
//处理查询结果
if(rs.next()){
return true;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}finally{
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return false;
}
在该方法中我们通过调用数据库连接对象的prepareStatement(sql)方法获取的是预编译的数据库操作对象,在获取预编译的数据库操作对象时需要传入SQL语句的框子,其中它用占位符?来代替sql语句要接收的值。然后我们再用setString(int parameterIndex, String x) 方法给占位符‘ ?’传值。
//关闭自动提交
conn.setAutoCommit(false);
//回滚事务
conn.rollback();
//提交事务
conn.commit();