jdbc:java database Connectivity(java连接数据库)
maven导入依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
一、使用步骤(固定六步)
1.注册驱动(作用:告诉java程序,即将要连接的是哪个品牌的数据库)
Class.forName("com.mysql.jdbc.Driver");
2.获取连接(表示JVM的进程和数据库之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭)
Connection connection = DriverManager.getConnection(url, username, password);
3.获取数据库操作对象(专门执行SQL语句的对象)
Statement st = connection.createStatement();
4.编写sql语句,并执行
String sql = "select * from smbms_bill where billCode='BILL2016_001'";
ResultSet resultSet = st.executeQuery(sql);
- int executeUpdate(String sql)专门执行DML语句的(insert,delete,update):返回值表示影响的行数
- ResultSet executeQuery(String sql)专门执行DQL(select)的语句,返回一个ResultSet类型的结果集
5.处理查询结果集(只有当第四步执行的是select语句时,才需要处理查询结果集)
while(resultSet.next()){
System.out.println("id="+resultSet.getObject("id"));
System.out.println("billCode="+resultSet.getString("billCode"));
System.out.println("productName="+resultSet.getObject("productName"));
System.out.println("---------------------------");
}
结果集图解:
6.关闭资源,一定要关,先开的最后关(使用完资源后,一定要关闭资源。java和数据库属于进程间的通信,开启之后一定要关闭)
- 为了保证资源一定关闭,通常放在finally语句块中关闭
- 并且要遵循从小到大依次关闭
- 并且分别对其try…catch
resultSet.close();
st.close();
connection.close();
二、自己封装DbUtil工具类
package com.yl.Utils;
import java.sql.*;
public class DbUtil {
public static final String URL = "jdbc:mysql://localhost:3306/yulu";//yulu为要连接的数据库名
public static final String USER = "root";
public static final String PASSWORD = "123456";
private static Connection conn = null;
static{
try {
//1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
//2. 获得数据库连接
conn = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
return conn;
}
}
在其他程序中调用如下:
public class JdbcTest02 {
public static void main(String[] args) throws SQLException {
//1.注册驱动,获取连接(通过直接调用封装类方法来实现)
Connection connection = DbUtil.getConnection();
//2.获取预编译的对象,并传入sql
String sql = "delete from user where id = ? ";//删除一行
PreparedStatement ps = connection.prepareStatement(sql);
//3.传参
ps.setString(1,"001");
//4.执行
ps.executeUpdate();
//5.关闭资源
ps.close();
connection.close();
}
}
三、其他问题
1.SQL注入问题
-
什么是sql注入:发送sql语句给DBMS,DBMS进行SQL编译。正好将用户提供的非法信息编译进去,导致原SQL语句的含义被扭曲了
-
如何解决sql注入问题
只要用户提供的信息不参与sql语句的编译过程,问题就解决了。
(解决问题的关键)即使用户提供的信息中含有sql语句的关键字,但是没有参与编译,就不起作用。
要想用户信息不参与sql语句的编译,那么就必须使用java.sql.PreparedStatement(这才是以后常用的)
-PreparedStatement接口继承了java.sql.Statement
-PreparedStatement是属于预编译的数据库操作对象
-PreparedStatement原理是:预先对sql语句的框架进行编译,然后再给sql语句传“值” -
对比Statement和PreparedStatement
Statement存在SQL注入问题,而PreparedStatement解决了SQL注入问题。
Statement是编译一次,执行一次;而PreparedStatement是编译一次,可以执行N多次。PreparedStatement效率高一些。
在mysql中,只要执行的语句完全一模一样,就不会重新编译,而只会直接执行。
PreparedStatement会在编译阶段做类型的安全检查。
绝大部分情况下需要使用PreparedStatement,而只有极少数的情况下才使用Statement。
- 什么情况下必须使用Statement?
业务方便必须支持SQL注入的时候(即业务要求需要进行sql拼接) 比如:按升序或是降序排序,desc/asc就得使用sql注入
2.PreparedStatement解释
获取预编译的数据库操作对象:
PreparedStatement prepareStatement(String sql)
String sql = "select * from t_userlogin where userName= ? and passWord= ?";//sql语句的框子
PreparedStatement ps = conn.prepareStatement(sql);//程序执行到此处,会发送sql语句框子给DBMS,然后DBMS进行sql语句的编译
ps.setString(1,"zhangsan");//表示给第一个占位符传值为“zhangsan”
ps.setString(2,"123456");//表示给第一个占位符传值为“123456”
ps.executeQuery();//执行
注意:
1.sql语句的框子。其中一个?表示一个占位符,一个?将来接收一个“值”。注意:占位符?不能使用单引号括起来。
2. 给占位符?传值(第1个问号下标是1,第2个问号下标是2,JDBC中所有的下标从1开始)
四、JDBC事务
public class TransactionTest {
@Test
public void test() {
Connection connection = null;
try {
//1.获取数据库连接
connection = DbUtil.getConnection();
//2.通知数据库开启事务,false为开启
connection.setAutoCommit(false);
//3.写SQL预编译
String sql = "update account set money = money-100 where id='1'";
connection.prepareStatement(sql).executeUpdate();
//4.制造错误1/0
int i = 1/0;//此处会发生异常
String sql2 = "update account set money = money+100 where id='2'";
connection.prepareStatement(sql2).executeUpdate();
connection.commit();//如果执行到此处便表明以上两条SQL都成功了,就提交事务
}catch (Exception e){
//如果出现异常就回滚事务
try {
e.printStackTrace();
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}finally {
try {
connection.close();//关闭资源
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
数据库事务语句:
start transaction ;#开启事务
update account set money = money-100 where id='1';
update account set money = money+100 where id='2';
rollback ;#回滚事务
commit ;#提交事务