Java基础28--JDBC概念、编写步骤、增删查改

Java基础28–JDBC概念

JDBC:
Java Database Connectivity Java连接数据库的技术。

JDBC通常指的是SUN为各大数据库厂商Java程序如何连接和操作它这个DBMS软件指定的统一的标准,即公共接口。
这个公共接口由各大数据库厂商提供实现类,这些实现类就构成了数据库驱动。

Java程序员编写Java代码时,只要面向接口编程就可以了,运行时把驱动实现类加到项目中即可。
Java程序员只要学习SUN公司提供的JDBC的公共接口就可以了。

如果自己新开发了一款数据库,想要Java程序连接它,需要实现这些JDBC的公共接口,否则无法连接。

mysql提供的驱动:两个版本的,使用时一个就行
在这里插入图片描述
在这里插入图片描述
jar包打开就是各种各样的接口、类
在这里插入图片描述
在这里插入图片描述

JDBC编写步骤

java.sql包和javax.sql包
JDBC是代表一组公共的接口。
JDBC中的这些公共接口和DBMS数据库厂商提供的实现类(驱动jar),是为了实现Java代码可以连接DBMS,并且操作它里面的数据而声明的。

常用的接口:
Connection:连接
Statement和PreparedStatement:增删改查
ResultSet:接收和处理查询结果

辅助的类:
DriverManager:驱动管理类。

JDBC程序的编写步骤:

  • 1、注册驱动(如果这步不做,编译不会报错,运行会报找不到驱动类等异常) java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/test
  • 2、连接数据库:
    DriverManager和Connection
  • 3、操作数据库 (1)增、删、改:Statement或PreparedStatement (2)查询:Statement或PreparedStatement
    ResultSet
  • 4、断开连接,关闭对应各种资源

url:统一资源定位符,通俗的讲就是网址
url是用来定位到①哪台电脑上的②哪种DBMS数据库软件,③访问哪个数据库,这个DBMS软件目前运行在④哪个断开号⑤连接这个DBMS软件是否还需要其他的参数。
url的标准格式:
协议://主机名:端口号/资源路径
mysql:
jdbc:mysql://主机名:端口号/数据库名?其他的参数
例如:
jdbc:mysql://localhost:3306/test

举例:

//添加案例,删除、修改只是sql语句不一样,其他步骤都一样
public static void main(String[] args) throws Exception {
		//1、注册驱动:把驱动类加载到内存,并且初始化这个类
		Class.forName("com.mysql.jdbc.Driver");//Class.forName()反射
		
		//2、连接数据库
		String url = "jdbc:mysql://localhost:3306/test";
		Connection conn = DriverManager.getConnection(url, "root", "1234");
		//java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)  
		//解决这个问题的思路:查看主机名,用户名,密码
		System.out.println(conn.getClass());//获取运行时类型   class com.mysql.jdbc.Connection
		
		//3、操作数据库
		//这里我要添加一条记录到User
		//(1)编写sql
		String sql = "INSERT INTO t_stu VALUES(3,'yan')";
		
		/*
		 * Connection好比网络编程中的Socket
		 * Statement好比和服务器进行数据读写的InputStream和OutputStream
		 */
		//(2)准备一个Statement   
		Statement st = conn.createStatement();
		
		//(3)执行sql,通过Statement对象把Sql发给服务器,服务器执行Sql后,把结果返回
		//insert ,update,delete语句都是通过这个方法执行
		int len = st.executeUpdate(sql);//返回的是受影响的记录的行数
		System.out.println(len>0?"添加成功":"添加失败");
		
		//4、释放资源
		st.close();
		conn.close();
	}

注册驱动三部曲:
(1)把jar放到项目的libs中
在这里插入图片描述

(2)把jar添加到build path中
在jar包上选择右键,Build Path–>Add to Build Path
在这里插入图片描述
不然会被当成普通文件
(3)在代码中注册驱动

Class.forName("com.mysql.jdbc.Driver");

JDBC实现查询

步骤:
1、注册驱动
三部曲:(1)把jar复制到libs(2)把jar添加到Build path中(3)加载驱动类
2、建立连接
获取Connection对象

3、执行sql
(1)编写sql
(2)创建Statement
(3)执行sql

增删改:int len = Statement对象.executeUpdate(sql)
查询:ResultSet rs = Statement对象.executeQuery(sql)

4、遍历结果集

5、关闭资源

	
	@Test
	public void test2()throws Exception{
		//1、加载驱动类
		Class.forName("com.mysql.jdbc.Driver");//之前那个
//		Class.forName("org.gjt.mm.Driver");//两个驱动的包都可以,二选一
		
		//2、建立连接
		String url = "jdbc:mysql://localhost:3306/test";
		Connection conn = DriverManager.getConnection(url,"root","1234");
		
		//3、执行sql
		String sql = "select * from t_stu";
		//sql语句也可以写为:String sql = "select sid,sname from t_stu";
		Statement st = conn.createStatement();
		ResultSet rs = st.executeQuery(sql);
		
		//4、遍历结果集
		/*
		 * rs.next():还有没有下一行
		 * rs.getXxx(字段名)
		 */
		while(rs.next()){
			int sid = rs.getInt("sid");
			String sname = rs.getString("sname");
			System.out.println(sid+"\t" +sname);
		}
		
		//5、关闭
		rs.close();
		st.close();
		conn.close();
	}

第二种方法:从查询结果里拿数据时也可以按字段的位置取值

@Test
	public void test4()throws Exception{
		//1、加载驱动类
		Class.forName("com.mysql.jdbc.Driver");
//		Class.forName("org.gjt.mm.Driver");
		
		//2、建立连接
		String url = "jdbc:mysql://localhost:3306/test";
		Connection conn = DriverManager.getConnection(url,"root","1234");
		
		//3、执行sql
		String sql = "select sid,sname from t_stu";
		Statement st = conn.createStatement();
		ResultSet rs = st.executeQuery(sql);
		
		//4、遍历结果集
		/*
		 * rs.next():还有没有下一行
		 * rs.getXxx(字段名)
		 */
		while(rs.next()){
			int sid = rs.getInt(1);//查询结果中的第一个字段
			String sname = rs.getString(2);//查询结果中的第一个字段
			System.out.println(sid+"\t" +sname);
		}
		
		//5、关闭
		rs.close();
		st.close();
		conn.close();
	}

甚至还可以写为:

	public void test5()throws Exception{
		//1、加载驱动类
		Class.forName("com.mysql.jdbc.Driver");
//		Class.forName("org.gjt.mm.Driver");
		
		//2、建立连接
		String url = "jdbc:mysql://localhost:3306/test";
		Connection conn = DriverManager.getConnection(url,"root","1234");
		
		//3、执行sql
		String sql = "select sid,sname from t_stu";
		Statement st = conn.createStatement();
		ResultSet rs = st.executeQuery(sql);
		
		//4、遍历结果集
		/*
		 * rs.next():还有没有下一行
		 * rs.getXxx(字段名)
		 */
		while(rs.next()){
			System.out.println(rs.getObject(1) + "\t" + rs.getObject(2));
			//数据类型不清楚的时候就都用object就行
		}
		
		//5、关闭
		rs.close();
		st.close();
		conn.close();
	}
	

org.gjt.mm.Driver驱动包
在这里插入图片描述

Statement问题

Statement问题:
1、SQL拼接:太麻烦
2、SQL注入:欺骗服务器执行恶意的SQL命令
3、无法处理blob等二进制类型的数据

如何解决这些问题,使用Statement的子接口PreparedStatement

public class TestStatementProblem {
	/*
	 * t_userinfo表
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| username | varchar(20) | NO   |     | NULL    |                |
| password | varchar(20) | NO   |     | NULL    |                |
| photo    | blob        | YES  |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
	 */
	 //三个问题示例
	@Test
	//无法处理blob等二进制类型的数据问题
	/*
	若是一张表中有字段是图片,图片存到数据库里不能是字符串、整数等类型,需要存储为二进制问题,比如blob类型,表结构如上图
     */
	public void test04()throws Exception{
		//往test库的t_userinfo表中添加一条记录
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
				
		//2、获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
		
		//3、编写sql
		String sql = "insert into t_userinfo values(null,'chai','1234', )";//这里怎么拼都是字符串,但是表中却是blob类型,无法存储,无法处理blob
		//这里id自增null就行
	}
	
	
	@Test
	public void test03()throws Exception{
		Scanner input = new Scanner(System.in);
		
		System.out.print("请输入员工的姓名:");
		String ename = input.nextLine();//若是inpur.next()的话遇到空格就输入结束,不正确,要用input.nextLine()
		System.out.println(ename);
		
	}
	
	@Test
	//sql注入问题
	public void test02()throws Exception{
		//员工自己查询自己的信息:从键盘输入员工的姓名,查询自己的信息
		Scanner input = new Scanner(System.in);
		
		System.out.print("请输入员工的姓名:");
		String ename = input.nextLine();//输入:孙红雷' or '1'='1,若是inpur.next()的话遇到空格就输入结束,不正确
		
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
				
		//2、获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
		
		//3、编写sql
		String sql = "select * from t_employee where ename = '" + ename + "'";
		System.out.println(sql);//select * from t_employee where ename = '孙红雷' or '1'='1'
			//这种编写sql语句的方法给了sql注入可乘之机!!!!!
			//'1'='1 永远成立,前面所有条件都是失效
	//会发现将整个表的数据都查出来了,不只是孙红雷的
	//会发现查询的结果不是sql语句想要查询的结构,恶意输入语句也可以实现某些功能
     //这种现象叫做sql注入
     
		
		//4、创建Statement
		Statement st = conn.createStatement();
		
		//5、执行sql
		ResultSet rs = st.executeQuery(sql);
		
		//6、遍历结果集
		while(rs.next()){
			for (int i = 1; i <= 14; i++) {
				System.out.print(rs.getObject(i) + "\t");
			}
			System.out.println();
		}
		
		//7、关闭
		rs.close();
		st.close();
		conn.close();
		input.close();
	
		}
	
	@Test
	//sql语句拼接问题
	public void test01()throws Exception{
		//从键盘输入部门的信息,添加到test库的t_department表中
		Scanner input = new Scanner(System.in);
		
		System.out.print("请输入部门的名称:");
		String dname = input.next();
		
		System.out.print("请输入部门的简介:");
		String desc = input.next();
		
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		
		//2、获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
		
		//3、编写sql
		String sql = "insert into t_department values(null,'" + dname + "','" + desc +"')";
		//dname,desc都是字符串,都需要单引号括起来
		//拼接麻烦
		
		//4、创建Statement
		Statement st = conn.createStatement();
		
		//5、执行sql
		int len = st.executeUpdate(sql);
		System.out.println(len>0?"添加成功":"添加失败");
		
		//6、关闭
		st.close();
		conn.close();
		input.close();
	}
}

PreparedStatement解决Statement问题

public class TestPreparedStatement {
	/*
	 * t_userinfo表
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| username | varchar(20) | NO   |     | NULL    |                |
| password | varchar(20) | NO   |     | NULL    |                |
| photo    | blob        | YES  |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
图片太大:
(1)表结构修改  把blob修改为mediumblob
mysql> desc t_userinfo;
+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| username | varchar(20) | NO   |     | NULL    |                |
| password | varchar(20) | NO   |     | NULL    |                |
| photo    | mediumblob  | YES  |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
(2)修改my.ini(修改配置文件,默认从客户端传到服务器的数据量的大小的限制
增加一个参数
max_allowed_packet=16m
在修改my.ini之前,关闭服务,修改之后重新启动服务
	 */
	@Test
	//解决blob问题
	public void test04()throws Exception{
		//往test库的t_userinfo标准添加一条记录
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
				
		//2、获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
		
		//3、编写sql
//		String sql = "insert into t_userinfo values(null,'chai','1234', )";//无法处理blob
		String sql = "insert into t_userinfo values(null,?,?,?)";//避免了拼接blob
		
		//4、创建PreparedStatement
		PreparedStatement pst = conn.prepareStatement(sql);
		
		//5、设置?
		pst.setString(1, "chailinyan");
		pst.setString(2, "123456");
		pst.setObject(3, new FileInputStream("D:/QMDownload/img/美女/15.jpg"));//不知道类型可以直接Object类型,这里报错图片太大,超过了
		//有pst.setBlob()方法,这里没讲使用方法;
		
		//6、执行sql
		int len = pst.executeUpdate();
		System.out.println(len>0?"添加成功":"添加失败");
		
		//6、关闭
		pst.close();
		conn.close();
	}
	
	@Test
	//避免sql注入
	public void test02()throws Exception{
		//员工自己查询自己的信息:从键盘输入员工的姓名,查询自己的信息
		Scanner input = new Scanner(System.in);
		
		System.out.print("请输入员工的姓名:");
		String ename = input.nextLine();//输入:孙红雷' or '1'='1
		
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
				
		//2、获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
		
		//3、编写sql
//		String sql = "select * from t_employee where ename = '" + ename + "'";
		String sql = "select * from t_employee where ename = ?";
		
		//4、创建Statement
//		Statement st = conn.createStatement();
		PreparedStatement pst = conn.prepareStatement(sql);
		
		//插入一步,设置?
		pst.setString(1, ename);
		
		//5、执行sql
//		ResultSet rs = st.executeQuery(sql);
		ResultSet rs = pst.executeQuery();
		
		//6、遍历结果集
		while(rs.next()){
			for (int i = 1; i <= 14; i++) {
				System.out.print(rs.getObject(i) + "\t");
			}
			System.out.println();
		}
		
		//7、关闭
		rs.close();
//		st.close();
		pst.close();
		conn.close();
		input.close();
	}
	
	@Test
	//避免sql拼接
	public void test01()throws Exception{
		//从键盘输入部门的信息,添加到test库的t_department表中
		Scanner input = new Scanner(System.in);
		
		System.out.print("请输入部门的名称:");
		String dname = input.next();
		
		System.out.print("请输入部门的简介:");
		String desc = input.next();
		
		//1、注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		
		//2、获取连接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "1234");
		
		//3、编写sql
//		String sql = "insert into t_department values(null,'" + dname + "','" + desc +"')";//不要拼接
		String sql = "insert into t_department values(null,?,?)";
		
		//4、创建PreparedStatement
//		Statement st = conn.createStatement();
		PreparedStatement pst = conn.prepareStatement(sql);//此时的sql带?的
		
		//加入一步,设置?的值
		pst.setString(1, dname);//1表示第1个?
		pst.setString(2, desc);//2表示第2个?
		
		//5、执行sql
//		int len = st.executeUpdate(sql);
		int len = pst.executeUpdate();//这里没有sql
		System.out.println(len>0?"添加成功":"添加失败");
		
		//6、关闭
//		st.close();
		pst.close();
		conn.close();
		input.close();
	}
}

修改my.ini文件
在这里插入图片描述
修改之前需要先将服务器停掉
在这里插入图片描述
停掉服务器
在这里插入图片描述
在文件的最后加上max_allowed_packet=16m(1
6是自己根据需要设置)

然后开启服务器
在这里插入图片描述

补充:blob相关的类型
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值