引言
上一讲讲到了Android如何通过JDBC连接到mysql远程数据库,什么?忘记啦!给你个传送门好好复习!
传送门: Android通过JDBC连接远程数据库
那么这讲本帅将接着上次未完待续的开始讲解,这讲你将会了解到:JDBC的增删改查操作,JDBCUtil封装的工具类,
废话不多说,现在开始吧!
JDBC的连接以及增删改查
基本步骤:
- 加载JDBC驱动管理器 { Class.forName(com.mysql.jdbc.Driver0)//加载类,名字为myql包下的jdbc的驱动类,为固定写法}
- 连接数据库
- 开启Statement,执行sql语句
- 得到结果集 (仅查找)
- 对结果集进行操作
- 关闭释放资源(栈式关闭,先关闭结果集,再关闭statement,最后关闭连接)
相信对于之前的学习,小伙伴们已经掌握了1,2步骤,具体伪代码实现如下:
1.Class.forName(com.mysql.jdbc.Driver);//类的加载(加载MySQL的JDBC驱动)
2.String url = jdbc:mysql://局域网ip:port/mysqldatabase
String username = root//本帅创建的可远程访问数据库的用户的用户名和密码
String password = “”;
Connection connection = DriverManager.getConnection(url,username,password);
这里看不懂的小伙伴接着回去复习~!
3.开启statement,执行sql语句(statement为陈述句)
其语法为: Statement stmt = connection.creatStatement();
stmt.execute(sql)
其中sql 语句有插入,删除,修改和查询,其中执行查询方法有返回结果集,见4
当执行删除/修改等sql语句时,若采用sql = ”delete form user where id =“ + id (有可能被sql注入)
sql注入: String id = ”1 or 1=1" 由于1==1恒成立,所以会删除数据表user中的所有数据
为了解决sql注入问题,采用PrepareStatement + 占位符的形式来防止sql注入
PreparedStatement ps = connection.preparedStatement();
如:sql = “delete from user where id= ?”//此处的?即为占位符
ps.setObject(1,2);//用准备好的陈述设置第一个问号的值为2
4.sql为查询语句时,有结果集
Resultset rs = stmt.executeQuery(sql)
5.通过rs.next方法,对结果集进行操作
6.关闭资源(rs,statement,connection)
example(insert)
JDBC执行插入代码如下:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class insert{
private static Statement stmt = null;//静态方法在类加载的时候就加载,所以stmt必须是static 类型
private static Connection connection = null;
public static void main(String[] args){
try {
//1.加载jdbc驱动类
Class.forName("com.mysql.jdbc.Driver");
//2.获取远程mysql连接(url(主要用到的是ip+port+databaseName),user,password(主要用到的是phpMyadmin创建的可远程访问的用户的用户名和密码))
String url = "jdbc:mysql://192.168.43.160:3306/test";//通过jdbx访问mysql数据库服务器,远程服务器ip为192.168.43.160 ,port为3306,数据库名称为 test
//phpMyadmin中创建的可远程访问权限的用户的用户名和密码
String user = "root";
String password = "";
connection = DriverManager.getConnection(url,user,password);//jdbc 连接上mysql服务器上的test数据库了
//3.开启sql称述,(Statement,PreparedStatement(?占位符形式)),执行sql语句
stmt = connection.createStatement();
String sql = "insert into user(id,username) values (1,'张大帅比')";
stmt.execute(sql);
//4.获取结果集(只有查询有)
//5.对结果集进行操作(只有查询有)
} catch (Exception e) {
e.printStackTrace();
}finally{
//6.对资源进行关闭(Resultset(此处没有),stmt,connection(采用栈式关闭)) 不能放入一个try catch 中,因为若一个执行失败,则其余资源也无法关闭
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Android stutdio 中未运行以上代码前
Android stutdio 中未运行以上代码后
至此,插入完毕!
example(delete)
JDBC执行删除代码如下:
package JDBC;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//删
public class deleteUtil {
private static PreparedStatement ps =null;
private static Connection connection=null;
public static void main(String[] args){
try {
//加载类驱动
Class.forName("com.mysql.jdbc.Driver");//通过反射加载jdbc驱动类
//获取连接
String url = "jdbc:mysql:// 192.168.43.160:3306/test";//用jdbc连接mysql下的服务器,服务器ip为192.168.43.160,数据库访问端口为3306,数据库名称为test
String user = "root";
String password = "";
connection = DriverManager.getConnection(url,user,password);
//创建陈述sql对象
String sql = "delete from user where id = 1";//删除id = 1 的记录
ps = connection.prepareStatement(sql);//有定义有准备的陈述sql
//设置占位符
ps.setObject(1,1);
int result=ps.executeUpdate();//executeUpdate方法如果有返回值,则代表该操作影响了返回值条记录
System.out.print(result);
} catch (Exception e) {
e.printStackTrace();
}finally{//栈式关闭资源(rs,ps,Connection)
try {
if(ps!=null){
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(connection!=null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
此代码运行完成后,删除数据库中id=1的记录,也即上图中的那条记录将被删除
运行代码前
运行代码后
此时可以看到,user表中id=1的记录全部被删除了,JDBC删除记录功能get!
看了以上的代码,相信聪明的小伙伴们已经发现了,虽然JDBC的记录插入和删除实现代码不一样,但还是存在相同的耦合的代码,
如第一步类的驱动加载,以及第二步的获取连接,以及最后的关闭资源等,代码都是一样一样的。想到一般情况下,同时只访问一个数据库下的不同表,本帅决定将耦合的代码重构,创建出一个JDBCUtil工具类,用以简化代码,明确逻辑,减少代码的耦合性。
分析:1.加载JDBC驱动类是固定写法,直接在JDBCUtil也如此写即可。
2.获取连接时主要通过以下几行代码实现
Connection connection = DriverManager.getConnection(url,username,password);
其中url 随着 访问的数据库的不同,服务器ip 和 数据库访问端口的不同而不同
而用户自定义的mysql可远程访问权想的用户也不尽相同,因此,我们需要在JDBCUtil中创建这些成员变量,当以上的某个值变化时方便改动,或者利用构造函数传入等。
3.关闭资源。关闭资源主要包含:关闭结果集rs,关闭Prestatement ps,关闭连接connection(栈式关闭)且为了防止前面的资源关闭出错,后续的关闭不执行,需要将其放在不同的代码块下。
综上我们可以写出JDBCUtil工具类的具体代码,如下所示:
JDBCUtil工具类
package JDBC;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* JDBC工具类 (通常将方法设置为静态方法,不然还要通过new 一个对象来调用方法,不优雅,类加载时即加载)
* 1.获取连接fangf
* 2.关闭释放jdbx使用的资源
* */
public class JDBCUtil {
private static Connection connection;
private static String url; //= "jdbc:mysql://"+ ip + ":" + port +"/"+ mysqldatabase
//远程访问mysql数据库权限用户的用户名和密码
private static String username = "root";//用户名通常为root
private static String password = "";//密码通常空
//服务器ip,数据库访问端口port,数据库名称mysqldatabase
private static String ip = "192.168.43.160";
private static int port = 3306;//数据库访问端口号通常为3306
private static String mysqldatabase = "test";
private static PreparedStatement ps;
/**1.
* 获取jdbc连接的方法getconnection (通过JDBCUtil.getConnection()来获取一个JDBC的连接)
* ip 为数据库所在的远程服务器的ip地址
* port 为数据库访问的端口
* mysqldatabase 要连接的数据库名称
* */
// public static Connection getConnection(String ip,String mysqldatabase){
public static Connection getConnection(){
try {
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//String url = "jdbc:mysql://ip:port/数据库名称";(port通常是3306,ip需输入,数据库名称需输入,用户名密码为PHPMyAdmin的进入密码)
//2.获取连接,url为jdbc连接:连接的mysql,服务器ip+数据库的名称 再由驱动管理者获取连接(url,username,password)
url = "jdbc:mysql://"+ ip + ":" + port +"/"+ mysqldatabase;
return connection = DriverManager.getConnection(url, username, password);
} catch (Exception e) {//捕捉所有的异常
e.printStackTrace();
}
return null;
}
/**2.
* 关闭,释放资源的方法close (若不存在使用下列资源,传递参数为null即可,通过JDBCUtil.close()关闭资源)
* rs 为结果集,通过JDBC查到的结果集,使用后需关闭释放资源
* stmt 为开启的sql语句
* connection 为jdbc的连接
* */
public static void close(ResultSet rs, Statement stmt,Connection connection){//栈式关闭(最先连接,最后关闭连接)
try{//关闭结果集
if(rs!=null) rs.close();
}catch (SQLException e){
e.printStackTrace();
}
try{//关闭sql语句
if(ps!=null) ps.close();
if(stmt!=null) stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
try{//关闭连接
if(connection!=null) connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
此时我们就能利用JDBCUtil类来简化我们的代码啦!
首先是获取连接代码 : Connection conection = JDBCUtil.getConnection();
使用完资源后关闭资源的代码:JDBCUtil.close();
至此,我们接下来的更新和查询都使用JDBCUtil封装的方法来简化实现,具体如下:
example(update)
JDBC执行更新代码如下:
package JDBC;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class updateUtil {
private static PreparedStatement ps=null;
public static void main(String[] args){
Connection connection = JDBCUtil.getConnection();
try {
String sql="update user set id= ?,username =? where id = ?";
ps = connection.prepareStatement(sql);
ps.setObject(1,3);
ps.setObject(2,"张大帅");
ps.setObject(3,1);
int result = ps.executeUpdate();
System.out.print(result);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtil.close(null,ps,connection);
}
}
}
执行代码前
执行代码后
至此,咱们写的JDBCUtil工具类经检测可以使用,JDBC的更新操作也能完美执行啦!
example(query)
使用JDBC查询操作的代码如下:
package JDBC;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class queryUtil {
private static PreparedStatement ps=null;
private static ResultSet rs = null;
public static void main(String[] args){
Connection connection = JDBCUtil.getConnection();
try {
String sql="select * from user ";
ps = connection.prepareStatement(sql);
rs =ps.executeQuery();
while (rs.next()){//游标结果集不为空,则输出
System.out.print(rs.getInt(1)+"--"+rs.getString("username"));
//System.out.print(String.valueOf(rs.getClob(2)));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.close(rs,ps,connection);
}
}
}
当执行以上代码时,此时数据库中的内容就打印出来了,如下图:
至此,JDBC的查询操作也完美收官。
附:JDBC出错处理:
当jdbc语句出错时,找到dao类,将sql语句复制粘贴到PHPmyAdmin里。
如:
在phpadmin服务器上执行一遍看能不能执行,能执行则没有错误。
结语
好啦,这次的博客到这里就要跟大家说再见啦!截止到这篇博客,JDBC的讲解也暂时告一段落了,下一次帅比本帅将记录本帅在使用PHPMyadmin创建数据库时,所遇到的数据库插入中文的编码问题,以及JDBC在Android跑起来的实战。点个小手跟我一起期待后续吧!!