JDBC
定义:说白了,就是用java程序中写SQL语句,对Mysql数据库中的数据进行操作。
类库:java.sql *
本质上:SUN公司设计了一套接口JDBC,然后各大数据库厂家对该接口进行实现。
JDBC优点:降低了耦合度,不需要关心数据库是哪个品牌,每个Java程序员直接面向JDBC接口编程,不需要关心底层的实现,只要利用JDBC,就可以操作任何数据库。
驱动的意思就是每个公司自己实现的接口类的集合包。
JDBC流程:固定的六步
- 注册驱动(通知java程序我们即将要连接哪个品牌的数据库)
//1、注册驱动
try {
java.sql.Driver driver = new com.mysql.jdbc.Driver();
DriverManager.registerDriver(driver);
}catch(SQLException e){
e.printStackTrace();
}
第二种方式:类加载注册
Class.forName("com.mysql.cj.jdbc.Driver");
2.获取数据库连接(java进程和数据库之间的进程开启了,相当于IO流)
本机IP地址还可以写成127.0.0.1 或者 localhost;3306是MySQL端口号
//2、获取数据库连接
String url = "jdbc:mysql://localhost:3306/library";
String user = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url,user,password);
最终得到了一个数据库成功连接的对象。
3.获取数据库操作对象(这个对象是为了执行SQL语句的)
通过一个连接对象,是可以创建多个操作对象的。
//3、获取数据库操作对象
Statement statement = connection.createStatement();
4.执行SQL语句(执行CRUD语句)
JDBC中的SQL语句不需要以“ ;”结尾
执行查询语句是 executeQuery,返回值是int
执行增删改语句是 executeUpdate,返回值是ResurtSet (是一个查询结果集对象,查询的结果都在这个集合当中,最后需 要关闭释放)
//4、执行SQL语句
String insertSql = "insert into dept(deptno,dname,loc) values(50,'销售部','上海')";
int count = statement.executeUpdate(insertSql);
String selectSql = "select empno,ename ,sno from emp order by sal desc";
ResultSet rs = statement.executeQuery(selectSql);
5.处理查询结果集(如果第四步是select语句,才有第五步)
JDBC中所有的下标都是从1开始
6.释放资源(JDBC是进程之间的通信)
由于未来的开发都是在服务器上进行的,即main函数不会结束,始终运行,所以我们需要自主释放资源。
finally {
//6.先关闭ResyrtSet,再释放Statement,再释放Connection
//分别进行try catch处理
//放到finally中关闭
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
if(connection != null){
try{
connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
完整实例演示
import com.mysql.jdbc.Driver;
import java.sql.*;
public class My_test {
public static void main(String[] args) throws SQLException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//2、获取连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/library","root","123456");
//3、获取数据库操作对象
statement = connection.createStatement();
//4、执行SQL语句
String sql = "select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno";
resultSet = statement.executeQuery(sql);
//5、处理查询结果集
while (resultSet.next()){
String ename = resultSet.getString("ename");
String dname = resultSet.getString("dname");
System.out.println(ename + "," + dname);
}
} catch (SQLException e) {
e.printStackTrace();
}finally { //6、关闭连接
if(resultSet!=null)
{
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement!=null)
{
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
配置文件步骤:
-
先加一个文件(name.properties)在这个文件里面加入配置文件
-
利用Bundle函数绑定上述文件
//资源绑定器 ResourceBundle bundle = ResourceBundle.getBundle("resources/db"); String driver = bundle.getString("driver"); String user = bundle.getString("user"); String url = bundle.getString("url"); String password = bundle.getString("password");
SQL注入:
本质上:由于statement是对sql命令语句的字符串拼接,导致了可以用户自主的通过更改输入的字符串从而扭曲SQL命令语句的含义,造成后台信息的泄露。
解决办法:使用prepareStatement,即先编译sql语句,空出指定位置传入用户输入的值,从而实现了“值是值”、“语句是语句”的状态,即用户的输入无法对sql语句命令造成歧义扭曲。
statement:优点:可以进行sql语句的拼接。
缺点:容易造成sql注入现象的出现。
preparestatement :优点:避免sql注入。
缺点:没有办法实现sql语句的拼接,只能给sql语句传值。
为什么一定要sql语句呢?
答:sql语句不仅仅是传值,还有单纯的语法操作,比如升序、降序命令
sql语句:order by desc (降序)
sql语句:select number from student where ‘1’ = ‘1’(这就是值,都会用单引号引起来)
处理事务机制:
1.拿到数据库的连接后,马上手动关闭jdbc自动提交机制(每进行一次dml命令,就直接传给数据库执行,类似脚本的概念)
connectioon.setAutoCommit(false)
2.事务执行结束之后,手动提交(当事务进程完全成功结束之后,将以上的dml语句依次交给数据库进行执行,确保事务的安全性和完整性)
3.如果事务出生错误或异常,则进行回滚。(即复原事务之前的操作)【其实是没有必要的,因为根本事务就没有执行,但是这是为了保险起见】