jdbc编程

8 篇文章 0 订阅
本文详细介绍了JDBC的基础知识,包括导入驱动、获取数据库连接、执行CRUD操作及资源释放。通过示例展示了如何使用JDBC进行插入、删除、更新和查询操作。此外,还讨论了SQL注入问题并提出了PreparedStatement的解决方案。最后,通过创建工具类实现了JDBC操作的代码复用,简化了数据库交互过程。
摘要由CSDN通过智能技术生成

Jdbc高级编程

1.JDBC就是Java链接数据库进行增删改查(curd)

Jdbc是一种用于执行sql语句的java api,可以为多个数据库提供统一的访问方式,它是由java语言编写的类和接口组成;
在没有jdbc之前程序员是怎么做的
没有jdbc的时候,java程序员编写了一套程序连接mysq 数据库,那么我就要连接mysql的驱动api,再连接。想要换到连接oracle数据库,这个时候又需要连接oracle驱动api。
这个时候sun公司提供了一套统一的规范(接口),然后所有的数据库厂商提供了这些接口的实现类,这套规范其实就jdbc

2.Jdbc 入门

只有以下四步骤:

2.1 导入jar包,加载驱动
Class.forname(‘驱动路径‘);
Class.forname(com.mysql.jdbc.Driver);
2.2 获取链接(java代码和数据库链接 url username password)
Connection 定义一个对象名= Drivermanager.getConnection(url,user,passwor);

端口号是应用程序的唯一标识
Jdbc 协议:数据库类型://地址:端口号:/具体数据库

2.3 基本操作

编写sql语句;

Update 表名 set 字段名 = 目标值 where 字段名 = 目标值;//将具体一条记录改变
Delete from 表名 where 字段名 = 目标值;//删除一条记录
Insert into 表名 values (内容……);添加所有内容;
Insert into 表名(字段名字1,字段名字2) values (1,值2.).//具体字段添加内容
Select :查询:
2.4 释放资源

与上面的2.1—2.4一一对应

第一步:驱动的导入和加载:(一般来说驱动都导入了的,只需要导包即可)

驱动的导入
1从项目文件夹名字下 (new一个)新建floder文件夹命名位lib(library的意思)
2将文件拷贝到lib文件下;
3找到拷贝好的文件,然后选中此文件,再右键,选择Build Path 就行了
驱动的位置:
要么记住位置
要么在导入的jar包内部找到Driver文件 此文件是不带后缀名的
然后选中,右键 选择Copy Qualified Name 这样驱动的路径就复制到鼠标上了,只需要praste
驱动的加载
Class.forName(驱动路径);

第二步:获取链接 Connection

格式:
Connection 链接名字 = DriverManager.getConnection();

第三步:基本操作
第四步:connection 、Statement 、PreparedStatement、ResultSet的释放

例子:

写一个使用jdbc操作数据库db1中的user表 以下的都是user的操作,

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Test01 {
	public static void main(String[] args) throws ClassNotFoundException, SQLException { 
//第一步加载驱动
		Class.forName("com.mysql.jdbc.Driver");
//第二步获取链接
		Connection cnct = DriverManager.getConnection//要释放
		("jdbc:mysql://localhost:3306/db1","root","123");

解释:
jdbc:mysql://localhost:3306/db2
jdbc 协议
mysql 连接mysql
localhost :连接数据库的ip地址 192.168.3.111 ,
localhost 本地
3306   端口号
db2 库名
		System.out.println(cnct);//这一步可以看connection是否链接正确
//第三步 
		//写sql语句  
		String s1 = "select *from exam";
		//获取执行sql语句的对象
		Statement st1 = cnct.createStatement();//要释放
		//执行sql语句
		ResultSet result =  st1.executeQuery(s1);//要释放
		while(result.next()) {
			System.out.print(result.getInt("id")+" ");
			System.out.print(result.getString("name")+" ");
			System.out.print(result.getInt("english")+" ");
			System.out.print(result.getInt("chinese")+" ");
			System.out.print(result.getInt("math")+" ");
			System.out.println();
		}
//第四步:释放资源
		result.close();
		st1.close();
		cnct.close();
	}
}

最基本的insert delete update select 语句的书写

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * 使用方法来完成CURD 原始代码
 * @author zj
*/
public class JdbcDemo2 {
	public static void main(String[] args) {//这里是主函数调用下面的方法
			try { //捕获异常
				//有可能出现异常的代码
				demo2();
			} catch (ClassNotFoundException | SQLException e) {
				//如果出现异常了 就执行这里的代码
				e.printStackTrace();
			}
	}
//插入方法 insert 添加内容的语句
	public static void demo1() throws ClassNotFoundException, SQLException {
//1加载驱动com.mysql.jdbc.Driver.class
		 Class.forName("com.mysql.jdbc.Driver");
//	2:获取连接
		 Connection conn = DriverManager.getConnection
				 ("jdbc:mysql://localhost:3306/day05", "root", "123");
//	3:基本操作
		 //3.1 获取执行sql语句的对象 使用connecttion对象来创建
		 Statement stmt = conn.createStatement();
		 //3.2 编写sql语句
		 String sql = "insert into user values(null,'ccc','111','喜羊羊',6)";
		 //3.3 执行sql语句 num 是执行了几条语句 使用connection创建的对象来调用executeUpdate
		 int num = stmt.executeUpdate(sql);//返回值是一个int 并且调用成功就返回值1,失败返回0
		  if(num>0) {
			  System.out.println("用户保存成功");
		  }
//	4:释放资源
		   stmt.close();
		   conn.close();
	}
//删除的方法 delete 某条记录
	public static void demo2() throws ClassNotFoundException, SQLException {
		//1加载驱动com.mysql.jdbc.Driver.class
		 Class.forName("com.mysql.jdbc.Driver");
//	2:获取连接
		 Connection conn = DriverManager.getConnection
				 ("jdbc:mysql://localhost:3306/day05", "root", "123");
//	3:基本操作
		 //3.1 获取执行sql语句的对象
		 Statement stmt = conn.createStatement();
		//3.2 编写sql语句
		 String sql = "delete from user where id =3";
		 //3.3 执行sql语句   num 是执行了几条语句
		 int num = stmt.executeUpdate(sql);
		 if(num>0) {
			  System.out.println("用户删除成功");
		  }
//	4:释放资源
		   stmt.close();
		   conn.close();
		
	}
//更改的方法 update
	public static void demo3() throws ClassNotFoundException, SQLException {
//1加载驱动com.mysql.jdbc.Driver.class
		Class.forName("com.mysql.jdbc.Driver");
//	2:获取连接
		Connection conn = DriverManager.getConnection
				("jdbc:mysql://localhost:3306/day05", "root", "123");
//	3:基本操作
		//3.1 获取执行sql语句的对象
		Statement stmt = conn.createStatement();
		//3.2 编写sql语句
		String sql = "update user set username ='懒洋洋' where id = 4";
		//3.3 执行sql语句   num 是执行了几条语句
		int num = stmt.executeUpdate(sql);
		if(num>0) {
			System.out.println("用户更改成功");
		}
//	4:释放资源
		stmt.close();
		conn.close();
	}
}

创建一个工具类

从以上的insert delete update方法可以看出;有四部分重复

1 驱动加载

2 获取链接 (当数据库改变的时候链接也要改变但这里一般使用一个数据库,所有就封装起来)

3 insert delete update 内部的基本操作 它们都调用同一个方法executeUpdate(写一个封装的方法:传递一个sql语句字符串)

Select使用的executequery方法

4 释放

由于加载驱动和获取连接以及释放资源的代码都一样,创建一个工具类,以后这个代码就直接使用工具类里的,不需要自己重复写。

工具类代码如下:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//定义的工具类的名字
public class JDBCUtils {
	private static final String s = "com.mysql.jdbc.Driver";
	private static final String url = "jdbc:mysql://localhost:3306/db1";
	private static final String user = "root";
	private static final String password = "123";
//	private static final String test = "select *from student";
//加载驱动的方法 lodeDriver 无参数
	public static void lodeDriver() throws ClassNotFoundException {
		Class.forName("com.mysql.jdbc.Driver");
	}
//创建链接的方法getConnection 返回值是个Connection 无参数
	public static Connection getConnection() throws ClassNotFoundException, SQLException {
		lodeDriver();
//可以直接创建链接跳过,驱动加载的步骤,因为有前面的lodeDriver()
		return DriverManager.getConnection(url, user, password);
	}
//以下释放语句1 close 有参数一个为Connection 另一个为Statement 
//注意 preparedStatement 是 Statement的子类所以也可以调用此方法
	public static void close(Connection cnt,Statement st ){
		try {
			cnt.close();
			st.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
//以下释放语句2 三个参数 因为select语句中有着 ResultSet这个对象
	public static void close(Connection cnt,Statement st,ResultSet rs){
		try {
			cnt.close();
			st.close();
			rs.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
//添加内容的语句;参数为sql语句,并且返回String作为标记添加成功或者失败
//此方法 @author ygj
	public static String add(String str) throws SQLException, ClassNotFoundException {
		Connection cnt = getConnection();
		Statement st = cnt.createStatement();
		int num = st.executeUpdate(str);
//		st.executeQuery(str);
		if(num>0) {
			return "success";
		}else{
			return "failed";
		}
	}

Sql注入问题(重要)例子:登陆

先使用statement对象来做 会出现注入
最后改进使用preparedStatement对象来做 就可以了
下面代码是使用statement对象来做的登录
使用的是user代码

Use db1;
Create table user(
id int primary key auto_increment ,
name varchar(20),
password int);
insert into user values(null,’张三’,123);
insert into user values (null,’李四’,125);

以下是使用statement对象执行sql语句

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.util.JDBCUtils;//导入自己创建的工具类包


//创建使用Statement执行sql语句的类 类名叫做UserDao_Statement
public class UserDao_Statement {
//定义名叫login的非静态方法,返回值是一个boolean类型
//要做登陆,自然要比较登陆名以及密码,所以两个参数 都是String类型;
//注意在表中password是int类型(无论是int 类型和字符串相加 结果也是一个字符串)
	public boolean login(String name,String pwd) {//两个参数 返回boolean
		Connection cnt = null;
		Statement st=null;
		ResultSet rs=null ;
		try {
		//加载驱动和创建链接
		cnt = JDBCUtils.getConnection();//调用jdbcutils里面的创建链接的方法
//编写sql语句
	String str = "select *from user where name ='"+name+"'and password ='"+pwd+"'";
	//要特别注意这几个单引号

//注意这里的password int 类型,当它加上了单引号会不会报错;答案是不会报错
	pwd有引号:Where name = ‘张三’ and password =123;
	pwd无引号:Where name = ‘张三’ and password = 123;
	以上的查询结果相同

//使用connection获取对象
	st = cnt.createStatement();//上面提到 st是个Statement类型
//使用上面的对象执行select语句
			rs = st.executeQuery(str);//返回只有一条语句 rs是个ResultSet类型
//JDBCUtils.getConnection().createStatement().executeQuery(str);
//这句话将加载驱动、创建链接、获取对象、执行select语句合为一句了
	  if(rs.next()) {//用的if语句 做登陆不会有两个相同的名字
				//rs.next() 如果有下一个则返回true
//get后面的和表的字段类型一致
//括号内的和字段名字一致 加上双引号
				System.out.println(rs.getInt("id"));
				System.out.println(rs.getString("name"));
				System.out.println(rs.getInt("password"));
				return true;
			}
		} catch (ClassNotFoundException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
//finally语句始终要执行:用来做释放语句最好了
			JDBCUtils.close(cnt, st, rs);
		}
		return false;


/*注意这两个return try和catch里面的return 语句会在把try、catch和finally一起*执行完之后(没有异常自然只执行完try和finally语句)才会return,这个return是try *catch里面的return。在finally后面的return,自然没有用了。当if语句条件不满足,*则不执行if语句内部,不会有try里的return。所以最终返回最后的return
*/
//如果是finally里面有return语句,则无论如何都返回finally里面的语句
	}
} 

PreparedStatement对象执行sql语句(非常重要)

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.util.JDBCUtils;//导包  工具包

public class UserDao02_preparedStatement {
	public boolean login(String name,String pwd) {
		Connection cnt=null;
		PreparedStatement pst=null ;
		ResultSet rs=null;
		try {
//创建连接 和加载驱动
			cnt = JDBCUtils.getConnection();
//sql语句
//用问号占位
			String str = "Select *from user where name =? and password = ?";
//用Connection获取prepareStatement对象,并且添加sql语句到()内 差别
			pst = cnt.prepareStatement(str);
//set后面的可以是int double date String 要和括号内部的类型对应
			pst.setString(1, name);
//数字1代表第一个问号,后面的是传进来的字符串
			pst.setString(2, pwd);
//执行sql语句 对象.executeQuery()
			rs = pst.executeQuery();
			if(rs.next()) {
				System.out.println(rs.getInt("id"));
				System.out.println(rs.getString("name"));
				System.out.println(rs.getInt("password"));
				return true;
			}
		} catch (ClassNotFoundException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JDBCUtils.close(cnt, pst, rs);
		}
		return false;
	}
}

以下是调用这两个类中方法的main

/**
 * 登录案例
*对数据库比较了解
 *我只要知道用户名就可以登录成功  其实是因为sql注入
*解决方案 使用
 *preparedStatement 接口
 *preparedStatement 接口 可以预编译 使得我书写的sql语句格式提前被规定好,以后传递过来的变量
 *即使 有mysql 中的注释或关键字,都只当作字符串处理,不当作mysql中的关键字
 * *
 */

public class LoginDemo {
	public static void main(String[] args) {
		UserDao_Statement us = new UserDao_Statement();
		boolean bool = us.login("赵四' -- ", "123");
//这样也是正确结果后面的’-- 将后续语句注释掉了
//将放进去的字符串当成了sql语句
		if(bool) {
			System.out.println("success");
		}else {
			System.out.println("failed");
		}
		System.out.println("----------------");
UserDao02_preparedStatement us02 = new UserDao02_preparedStatement();
		boolean bool02 = us02.login("赵四' -- ", "123");
//使用preparedStatement 就不存在这个问题;
//有setString(int,double,date)将其设置为了固定的格式;
//就是一个类型参数而不是sql里面的语句
		if(bool02) {
			System.out.println("success");
		}else {
			System.out.println("failed");
		}
	}
	}

使用PreparedStatement 实现增删改查

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.util.JDBCUtils;
public class Test_preparedStatement_CURD {
	public static void main(String[] args) {
		insert();
		update();
		delete();
		select();
	}
//更改
	public static void update() {
		Connection cnt=null;
		PreparedStatement pst=null;
		try {
			cnt = JDBCUtils.getConnection();
			String str = "update user set name =? where id = ?";
			pst = cnt.prepareStatement(str);
			pst.setString(1, "张三");
			pst.setInt(2, 3);
			int num = pst.executeUpdate();
			if(num>0) {
				System.out.println("更改成功");
			}
		} catch (ClassNotFoundException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JDBCUtils.close(cnt, pst);
		}
	}
//添加记录
	public static void insert() {
		Connection cnt=null;
		PreparedStatement pst =null;
		try {
			cnt = JDBCUtils.getConnection();
			String str = "insert into user values(null,?,?)";
			pst = cnt.prepareStatement(str);
			pst.setString(1, "赵本山");
			pst.setInt(2, 112);
			int num = pst.executeUpdate();
			if(num>0) {
				System.out.println("添加记录成功");
			}
		} catch (ClassNotFoundException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JDBCUtils.close(cnt, pst);
		}
	}
//删除
	public static void delete() {
		Connection cnt = null;
		PreparedStatement pst = null;
		try {
			cnt = JDBCUtils.getConnection();
			String str = "delete from user where id = ?";
			pst = cnt.prepareStatement(str);
			pst.setInt(1, 14);
			int num = pst.executeUpdate();
			if(num>0) {
				System.out.println("删除成功了");
			}
		} catch (ClassNotFoundException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JDBCUtils.close(cnt, pst);
		}
	}
//查询
	public static void select () {
		Connection cnt = null;
		PreparedStatement pst = null;
ResultSet rs = null;
		try {
			cnt = JDBCUtils.getConnection();
			String str= "select *from user";
			pst = cnt.prepareStatement(str);
			rs = pst.executeQuery();
			while(rs.next()) {
				System.out.print(rs.getInt("id")+" ");
				System.out.print(rs.getString("name")+" ");
				System.out.print(rs.getInt("password")+" ");
				System.out.println();
			}
		} catch (ClassNotFoundException | SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JDBCUtils.close(cnt, pst,rs);
		}
	}
	}

Java语言中的事务手动开启事务

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.util.JDBCUtils;
public class Test_shiwu {
//事务jdbc
//事务是默认开启的
	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		update();
		update2();
	}
	public static void update () {
		Connection cnt = null;
		try {
			cnt.setAutoCommit(false);
			String str = "update account set money = money+? where name = ?";
			PreparedStatement pst = cnt.prepareStatement(str);
			
			//小黑给钱给小白
			pst.setDouble(1, -1000);
			pst.setString(2, "小黑");
			//执行减钱操作
			pst.executeUpdate();

			//执行小白加钱
			pst.setDouble(1, 1000);
			pst.setString(2, "小白");
			pst.executeUpdate();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
//手动开启事务
	public static void update2 () {
		Connection cnt = null;
		try {
			cnt = JDBCUtils.getConnection();
		//要使用链接的对象来调用事务,调用setAutoCommit();括号内部写false;
//关闭自动事务
			cnt.setAutoCommit(false);
			String str = "update account set money = money+? where name = ?";
			PreparedStatement pst = cnt.prepareStatement(str);
			//小黑给钱给小白
			pst.setDouble(1, -1000);
			pst.setString(2, "小黑");
			//执行减钱操作
			pst.executeUpdate();
			int i = 10/0;
//这里演示的是算术异常,是需要程序员自己解决的(而不是try catch)为了演示才找的除零异常
//内部异常的出现直接跳转到catch里面下面的语句不会执行
			//执行小白加钱
			pst.setDouble(1, 1000);
			pst.setString(2, "小白");
			pst.executeUpdate();
//提交事务
			cnt.commit();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
	//如果内部出现异常则直接跳到这里来。上面的commit()是最后一句,前面都没有异常才执行
			try {
//回滚,取消所有从事务开始的操作 
				cnt.rollback();
			} catch (SQLException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值