JDBC
1.概念:
Java Database Connectivity Java数据连接 Java语言操作数据库
JDBC的本质:其实是sun公司定义的一套操作所有关系型数据库的规则(接口)。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的是驱动jar包中的实现类。
2.jdbc访问数据库的步骤:
- 加载驱动----创建lib目录,导入驱动jar包,右键Add As Library
- 注册驱动 创建连接对象 Connection
- 定义sql语句
- 创建语句处理对象 Statement
- 执行sql 如果Sql是查询语句,需要创建结果集对象ResultSet
- 打印执行结果
- 释放资源
Class.forName("com.mysql.jdbc.Driver"); //加载驱动
//注册驱动
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名","root","root");
//定义修改sql
String sql="update atm set user_money=100 where user_id=1 ";
//定义查询sql
String sql="select user_money from atm where user_id=1 ";
//创建语句处理对象
Statement stmt = con.createStatement();
//1.修改sql-----执行sql
int i = stmt.executeUpdate(sql);
//打印执行结果
System.out.print(i);
//2.查询sql---如果是处理查询语句,需要结果集对象ResultSet
ResultSet rs = stmt.executeQuery(sql);
if(rs.next()){
输出你想输出的东西
}
//释放资源
rs.close();
stmt.close();
con.close();
3.详解各个对象
(1)DriverManager :驱动管理对象
功能:
1.注册驱动:告诉程序该使用哪一个数据库驱动jar包
static void registerDriver(Driver driver):注册与给定的驱动程序DriverManager。
写代码使用:com.mysql.jdbc.Driver
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤
2.获取数据库连接:
方法:static Connection getConnection(String url,String user,String password),返回一个Connection对象;
参数:
url是指定的连接路径
语法:jdbc:mysql://主机IP地址:端口号/数据库名
例如:jdbc:mysql://localhost:3306/atm
如果连接的是本机的mysql服务器,端口号默认是3306;那么可以写成jdbc:mysql:///数据库名称
user:用户名
password:密码
(2)Connection :数据库连接对象
1.获取执行sql语句的对象:
Statement createStatement();
PreparedStatement PrepareStatement(String sql);
2.管理事务:
开启事务:setAutoCommit(boolean autoCommit):调用该方法设置参数为false,开启事务
提交事务:commit()
回滚事务:rollback()
(3)Statement :执行(静态)sql语句的对象
1.执行sql
* boolean execute(String sql):可以执行任意sql
* int executeUpdate(String sql):执行的是DML语句(insert、update、delete),DDL语句(alter、drop、create)
返回值:影响的行数,可以判断语句是否执行成功。如果返回值>0则执行成功,否则失败
*ResultSet executeQuery(String sql):执行DQL语言(select)
练习:
修改user表中的数据
往user表中插入数据
删除user表中的数据
插入数据:(修改和删除只需要改变sql语句即可,就不放代码了)
Connection con = null;
Statement stmt = null;
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//加载驱动
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/user", "root", "root");
//定义sql语句
String sql="insert into s values ('2','肖森波',20)";
//获取处理sql语句的对象 Statement对象
stmt = con.createStatement();
//执行sql
int i = stmt.executeUpdate(sql);
if(i>0){
System.out.println("插入成功");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
(4)ResultSet :结果集对象,封装查询结果
方法:
boolean next():游标向下移动一行,判断当前是否为最后一行,如果是返回false,否则返回true
getXxx(参数):获取数据
Xxx代表数据类型:int getInt(),String getString()等等
参数:int 表示列的编号,从1开始 例如:getInt(1)
String 表示列的行号 例如:getString('name')
使用步骤:
1.游标向下移动一行
2.判断是否有数据
3.获取数据
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//注册驱动
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/user", "root", "root");
//定义sql语句
String sql="select * from s";
//创建处理对象
stmt = con.createStatement();
//处理语句
rs = stmt.executeQuery(sql);
while (rs.next()){
String id = rs.getString(1);
String name = rs.getString(2);
int age = rs.getInt(3);
System.out.println(id+" "+name+" "+age);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
(5)PreparedStatement :预编译,执行动态sql语句
1.sql注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。
用户随便输入密码:a' or 'a' = 'a 结果是登录成功
sql:select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'
2.解决sql注入的办法:使用PreparedStatement对象来解决
3.预编译处理的sql使用?作为占位符
4.使用步骤:
(1)导入jar包,加载驱动
(2)注册驱动
(3)获取数据库连接对象Connection
(4)定义sql语句
注意:sql的参数使用?作为占位符。
select * from user where user=? and password=?
(5)获取执行sql语句的处理对象PerparedStatement
Connection.preparedStatement(String sql)
(6)给?赋值
方法:SetXxx(参数1,参数2)
参数1:?的位置编号从1开始
参数2:?的值
(7)执行sql,接收返回结果 不需要传递sql
(8)处理结果
(9)释放资源
5.注意:后期都会使用PreparedStatement来完成增删改查的所有操作
优点:可以防止SQL注入 效率更高
抽取工具类JDBCUtils
抽取工具类可以提高代码的复用性,简化代码的书写
把需要传递的参数写进一个jdbc.properties文件中,每次只需要修改配置文件中的参数即可。获取文件的路径ClassLoader类加载器
1.需要抽取连接对象的方法
2.需要抽取释放资源的方法
3.注册驱动也需要抽取
jdbc.properties配置文件
url=jdbc:mysql://localhost:3306/user
user=root
password=root
driver=com.mysql.jdbc.Driver
代码展示
private static String url;
private static String user;
private static String password;
private static String driver;
/*文件的读取,只需要读取一次就可拿到,放在静态代码块中*/
static {
//读取资源,获取值
//1.创建Properties结集合类
Properties pro=new Properties();
//获取src路径下的文件---ClassLoader 类加载器
ClassLoader classLoader=JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
//2.加载文件
String path = res.getPath();
try {
pro.load(new FileReader(path));
//3.获取文件,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//注册驱动
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//抽取连接对象的方法
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
//抽取释放资源的方法
public static void close(ResultSet rs, Statement stmt,Connection con){
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}