使用JDBC连接数据库并操作的主要步骤
1.注册驱动
2.获取数据库连接
3.获取操作对象
4.执行sql语句
5.释放资源
具体步骤
1.导入mysql-connector-java的j驱动包(jar包),像下面这样的:
下载地址:mysql-connector-java-8.0.21.jar
2.创建一个数据库表,如下:
3.开始编写代码,如下:
import com.mysql.cj.jdbc.Driver;
import java.sql.*;
public class Test1 {
public static void main(String[] args) throws ClassNotFoundException {
Connection conn = null;
Statement stat = null;
try {
//1.注册驱动
//Class.forName("com.mysql.cj.jdbc.Driver");也可以注册驱动
//DriverManager.registerDriver,这个是注册驱动,底层用Class.forName反射机制来注册,然后因为Driver类里面有个静态代码块是注册的,所以加载类就会注册
DriverManager.registerDriver(new Driver());
//2.获取数据库连
/*
url:users为数据库名,注意mysql8的版本需要加上一个时区,否则运行会报错,直接在数据库名后面加"?serverTimezone=UTC"
user:数据库用户名
password:数据库密码
*/
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/tzm?serverTimezone=UTC", "root", "123456");
//3.获取操作对象
stat = conn.createStatement();
//4.执行sql语句
int i = stat.executeUpdate("update users set name='新张三' where id=1");
//返回的是一个int类型的值,表示的是受影响的记录条数
System.out.println(i);
//返回的是一个resultSet结果集,是一条条查出来的记录,有结果集的需要处理一下,进行遍历输出
ResultSet resultSet = stat.executeQuery("select * from users");
//开始指针位置位于第一行之前,也就是说,第一次调用next()方法后才能开始获取数据,只有遍历到最后一行之后,或者当 ResultSet 中没有记录,为0时,才会返回false退出循环。
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String age = resultSet.getString("age");
String sex = resultSet.getString("sex");
String hobby = resultSet.getString("hobby");
System.out.println(id + "---" + name + "---" + age + "---" + sex + "---" + hobby);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源,关闭连接
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
结果:
Statement与PreparedStatement
区别:
1、PreparedStatement可以使用占位符,是预编译的,批处理比Statement效率高
2、使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。
3、statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement预编译得, preparedstatement支持批处理 。
4、执行许多SQL语句的JDBC程序产生大量的Statement和PreparedStatement对象。通常认为PreparedStatement对象比Statement对象更有效,特别是如果带有不同参数的同一SQL语句被多次执行的时候。PreparedStatement对象允许数据库预编译SQL语句,这样在随后的运行中可以节省时间并增加代码的可读性。
5、 PreparedStatement 可以规避 Statement弊端:①拼串 ②sql注入问题
6、PreparedStatement 可以实现操作Blob类型、Clob类型的数据
联系:
1、PreparedStatement继承自Statement
2、PrerapedStatement和Statement都是接口
3、PreparedStatement和Statement都可以实现对数据表的CRUD操作:增删改查
大概意思就是指上面所用的Statement创建的对象,你会发现,执行sql语句时,都是把sql语句写死执行的
而下面这种用PreparedStatement创建出来的对象,可以使用一种占位符,也就是"?“,来代替sql语句中的参数
例如:update user set 张三=“新张三” and age=“28” where id=“1”
用了 PreparedStatement之后,用占位符代替sql语句里面的参数,就变成了:update user set 张三=”?" and age=“?” where id=“?”
那么问题来了,如何给"?"传参呢?这就需要用到PreparedStatement里面的setString()方法了,如下:
PreparedStatement stat=null;
...
/*
setString(1, "新张三");
参数一:"?"的下标index,注意是从1开始的,不是0!!!
参数二:需要给"?"传递的值
*/
stat.setString(1, "新张三");
stat.setString(2, "28");
stat.setString(3, "1");
stat.executeUpdate();//执行sql,增删改都用executeUpdate,查就用executeQuery
下面是完整的例子:
import java.sql.*;
import java.util.Scanner;
//使用PreparedStatement的场景,通过键盘输入进行传值。
public class Test8 {
public static void main(String[] args) throws ClassNotFoundException {
Scanner scanner = new Scanner(System.in);
System.out.println("输入需要修改的姓名:");
String oldName = scanner.nextLine();
System.out.println("输入新的姓名:");
String newName = scanner.nextLine();
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = null;
PreparedStatement stat = null;
try {
//2.获取数据库的连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/tzm?serverTimezone=UTC", "root", "123456");
//3.获取操作对象
stat = conn.prepareStatement("update set username = ? where username = ?");
stat.setString(1, newName);//给第一个"?"进行赋值
stat.setString(2, oldName);//给第二个"?"进行赋值
//4.执行sql语句
stat.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源,关闭连接
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
注意事项:
1.index下标是从1开始,也就是从第一个问号开始
2.赋值的时候不需要为字符串变量的两边加上’’
直接ps.setString(1, “liguang”);
3.占位符只能替换值类型,不能替换表名、字段名或者其他关键词。
4.PreparedStatement会为占位符"?"的两边自动加上单引号,有时候这样会使得SQL语句不可执行,比如使用将表名设置为占位符,数据库执行sql语句时,表名会用单引号引起来,这样会使得sql语句执行出错或者查询不出数据。所以Statement与PreparedStatement要看实际场合,合理使用。
jdbc常用的方法接口
java.sql.* 和 javax.sql.*
1. Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商要来实现此接口。
connect(url, properties): 连接数据库的方法。
url: 连接数据库的URL
URL语法: jdbc协议:数据库子协议://主机:端口/数据库
user: 数据库的用户名
password: 数据库用户密码
2. DriverManager类: 驱动管理器类,用于管理所有注册的驱动程序
registerDriver(driver) : 注册驱动类对象
Connection getConnection(url,user,password): 获取连接对象
3. Connection接口: 表示java程序和数据库的连接对象。
Statement createStatement() : 创建Statement对象
PreparedStatement prepareStatement(String sql):创建PreparedStatement对象
CallableStatement prepareCall(String sql):创建CallableStatement对象
4. Statement接口: 用于执行静态的sql语句
int executeUpdate(String sql) : 执行静态的更新sql语句(DDL,DML)
ResultSet executeQuery(String sql) :执行的静态的查询sql语句(DQL)
5. PreparedStatement接口:用于执行预编译sql语句
int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)
ResultSet executeQuery() : 执行预编译的查询sql语句(DQL)
6. CallableStatement接口:用于执行存储过程的sql语句(call xxx)
ResultSet executeQuery() : 调用存储过程的方法
7. ResultSet接口:用于封装查询出来的数据
boolean next() : 将光标移动到下一行
getXX() : 获取列的值