javaWeb归纳

一.JDBC概述

概念作用
JDBC (Java DataBase Connectivity) java连接数据库 技术。
JDBC可以实现java语言对数据库表数据的增删改查操作。Java负责后台程序业务逻辑编写的,sql负责数据库增删改查的操作的,我们不能直接使用java去操作sql语言。在这个过程中我们需要一个连接的桥梁或者叫纽带,JDBC就是扮演了这个连接的角色。
JDBC技术可以实现java和多种数据库的连接:mysql sqlserver oracle

下载
JDBC由第三方团队开发,提供给开发者使用,我们做为开发人员只需要掌握其使用方法及常用API即可,至于技术的升级和维护不需要我们去考虑。JDBC是以jar包的形式提供给我们使用,所以我们使用之前需要先下载jar包(封装的java类 .jar文件)。
下载地址:
https://downloads.mysql.com/archives/c-j/
解压
mysql-connector-java-5.1.40-bin.jar就是我们需要的JDBC驱动jar包。

JDBC连接步骤
① 创建java项目,导入下的JDBC驱动包
② 加载JDBC驱动包到程序
③ 创建JDBC连接对象Connection
④ 创建sql的执行对象
⑤ 执行目标sql语句
⑥ 处理执行sql结果返回值
⑦ 关闭连接,释放资源

JDBC入门案例
入门案例实现
1、创建java项目,导入JDBC驱动包
2、编写入门案例代码

public class JDBCTest {

	public static void main(String[] args) throws ClassNotFoundException, SQLException {
		//1.加载JDBC驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2.创建连接对象
		String url="jdbc:mysql://localhost:3306/mysql0202";//连接的目标数据库
		String user="root";//mysql登录账号
		String password="root";//mysql登录密码
	    Connection connection=DriverManager.getConnection(url, user, password);
		//3.创建sql执行对象
		Statement statement=connection.createStatement();
		//4.执行目标sql语句
		String sql="INSERT INTO students (sname)VALUES(\"张三丰\");";
		int row=statement.executeUpdate(sql);
		//5.处理执行sql的结果
		System.out.println(row);
		//6.关闭连接对象,释放资源
		statement.close();
		connection.close();
		
	}
}

入门案例参数说明
以上案例中使用的API都来自于我们的jdk文档中。
//1.加载JDBC驱动:反射技术加载类字节码对象
Class.forName(“com.mysql.jdbc.Driver”);//使用反射将编译后的.class文件加载到内存中,jvm就可以执行这个文件
//2.创建连接对象
//jdbc:mysql使用jdbc连接mysql数据库
//localhost=127.0.0.1本机回环地址
//3306mysql默认端口号
//mysql0202目标数据库名称
String url=“jdbc:mysql://localhost:3306/mysql0202”;//连接的目标数据库
String user=“root”;//mysql登录账号
String password=“root”;//mysql登录密码
//DriverManager是JDBC驱动的管理对象,可以将驱动引入到程序中加载
//getConnection(url, user, password);创建连接对象的方法
//Connection连接java代码和mysql数据库的一个管理对象
Connection connection=DriverManager.getConnection(url, user, password);
//3.创建sql执行对象:执行sql语句的对象
//Statement对象中提供了对数据库表增删改查的API
//增删改:int num=executeUpdate(String sql);
//查询:ResultSet rs=executeQuery(String sql);
Statement statement=connection.createStatement();
//4.执行目标sql语句
String sql=“INSERT INTO students (sname)VALUES(“张三丰”);”;
//row表示影响数据库表的行数
int row=statement.executeUpdate(sql);
//5.处理执行sql的结果
System.out.println(row);
//6.关闭连接对象,释放资源
statement.close();
connection.close();
注意事项:
1、我们的对象全部在java.sql包下面
2、需要我们掌握的核心的JDBC对象
连接对象:Connection
sql执行器对象:
执行sql增删改查的方法
查询的返回的结果集对象:里面封装了查询的表中的所有数据

二.单元测试

单元测试
功能和main函数类似,也是对代码段进行测试使用,但是一个java文件中可以设置多个单元测试的方法。这些方法都是相互独立运行的。
单元测试添加
1、eclipse设置添加
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、代码中添加注解
在这里插入图片描述

单元测试使用:代码调试


```java
/**
 * 单元测试
 * @author admin
 *
 */
public class JDBCDemo1 {
	/**
	 * 修改学生信息
	 */
	@Test
	public void student_update() {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql0202",
					   "root","root");
			Statement statement = connection.createStatement();
			int row = statement.executeUpdate("UPDATE students SET sname=\"关羽\" WHERE sid=4");
			System.out.println(row);
			statement.close();
			connection.close();
		} catch (Exception e) {
			
			e.printStackTrace();
		}
	}
	/**
	 * 删除学生信息
	 */
	@Test
	public void student_delete() {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql0202",
					   "root","root");
			Statement statement = connection.createStatement();
			int row = statement.executeUpdate("DELETE FROM students WHERE sid=4");
			System.out.println(row);
			statement.close();
			connection.close();
		} catch (Exception e) {
			
			e.printStackTrace();
		}
	}
	
	
}
/**
	 * 查询所有学生信息
	 */
	@Test
	public void student_show() {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			//localhost:3360当连接的是本地电脑mysql 3306端口号没有改变  可以省略不写
			Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0202","root","root");
			Statement statement = connection.createStatement();
			//查询返回的结果集是一个set集合:学生数据存在set集合中
			ResultSet rs = statement.executeQuery("SELECT * FROM students");
			//遍历集合
			while(rs.next()) {//每次循环从表中获取一行学生数据
				/**
				 * ResultSet对象中提供了获取数据的方法:
				 * getXXX()根据数据库表字段的类型提供了相应的不同数据类型获取方法
				 * getInt()
				 * getString():getString(1)获取字符串类型的字段,通过字段的索引来获取
				 *            getString(sname)通过字段名称获取
				 * getObject()
				 * getDate()
				 */
				
				//获取学生的编号
				//int sid = rs.getInt("sid");
				//获取学生的姓名
				//String sname = rs.getString("sname");
				//推荐使用getObject()
				Object sid = rs.getObject("sid");
				Object sname = rs.getObject("sname");
				System.out.println(sid+"===="+sname);
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

Sql注入

1.登录功能实现
需求:
在客户端输入账号和密码,进行登录的操作,如果账号密码正确则登录成功,否则登录失败。
需要sql:
SELECT * FROM users WHERE username=“lisi” AND userpwd=“123456”;
代码示例:

/**
	 * 登录测试
	 */
	@Test
	public void user_login() {
		//创建输入的函数
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入账号:");
		String username = sc.nextLine();
		System.out.println("输入密码:");
		String userpwd = sc.nextLine();
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0203", "root", "root");
			Statement statement = connection.createStatement();
			String sql="SELECT * FROM users WHERE username='"+username+"' AND userpwd='"+userpwd+"'";
			System.out.println(sql);
			ResultSet rs = statement.executeQuery(sql);
			if (rs.next()) {
				System.out.println("登录成功");
			}else {
				System.out.println("登录失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

2.Sql注入问题
在这里插入图片描述
以上是登录的时候,使用特殊字符实现的sql注入效果。
Sql注入概念
在客户端输入一些特殊的字符,来对数据库服务器进行掩饰,从而达到一些非法的操作。这个操作是非常不安全的,我们在开发的时候是需要避免掉的。
Sql注入的解决方案:
我们不使用statement对象,使用预编译对象PreparedStatement对象。
查询预编译对象:
在这里插入图片描述

预编译对象PreparedStatement和执行器Statement的关系
1、PreparedStatement是Statement的子接口
2、statement是执行sql的时候进行sql的 编译,也就是静态的执行效果;PreparedStatement对象是一个预编译对象,在执行sql之前已经编译完成。并且在后期可以多次的执行编译后的sql。
3、Statement执行sql的时候,传入的参数参与了sql的编译过程;PreparedStatement执行sql的时候已经编译完成,传入的参数不会参与编译过程

Sql预编译对象使用

1.Sql注入问题解决

/**
	 * 解决sql注入
	 */
	@Test
	public void user_login1() {
		//创建输入的函数
				Scanner sc=new Scanner(System.in);
				System.out.println("请输入账号:");
				String username = sc.nextLine();
				System.out.println("输入密码:");
				String userpwd = sc.nextLine();
				try {
					Class.forName("com.mysql.jdbc.Driver");
					Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0203", "root", "root");
					String sql="SELECT * FROM users WHERE username=? AND userpwd=?";
					//预编译:创建sql执行器对象的时候对sql进行编译
					PreparedStatement ps = connection.prepareStatement(sql);
					/**
					 * 预编译机制使用了占位符操作:
					 * ?代码占位符,在编译的时候替换未知的变量值
					 * 
					 */
					//sql执行之前讲占位符替换成具体变量值
					ps.setObject(1, username);
					ps.setObject(2, userpwd);
					//SELECT * FROM users WHERE username=? AND userpwd=?
					System.out.println(sql);
					//执行sql的时候不需要编译sql
					ResultSet rs = ps.executeQuery();
					if (rs.next()) {
						System.out.println("登录成功");
					}else {
						System.out.println("登录失败");
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
	} 

小结:
1、预编译对象,使用了占位符机制在创预编译对象的时候将sql进行编译。
2、传入参数的时候,使用占位符替换变量值,
3、执行sql的时候,sql已经完成了编译过程,所以传入的参数就不会参与编译过程,从而避免sql注入问题。

2.增删改查实现
需求:使用预编译对象实现用户表CRUD操作。

代码示例:

/**
 * 查询用户信息
 */
@Test
public void user_show() {
	try {
		Class.forName("com.mysql.jdbc.Driver");
		Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0203", "root", "root");
		String sql="SELECT * FROM users";
		PreparedStatement ps = connection.prepareStatement(sql);
		ResultSet rs = ps.executeQuery();
		while(rs.next()) {
			System.out.println("账号:"+rs.getObject("username")+"\t密码:"+rs.getObject("userpwd"));
		}
		rs.close();
		ps.close();
		connection.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
	
}
/**
 * 删除用户信息
 */
@Test
public void user_delete() {
	try {
		Class.forName("com.mysql.jdbc.Driver");
		Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0203", "root", "root");
		String sql="DELETE FROM users WHERE uid=?";
		PreparedStatement ps = connection.prepareStatement(sql);
		ps.setObject(1, 4);
		int row = ps.executeUpdate();
		System.out.println(row);
		ps.close();
		connection.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
	
}
/**
 * 修改用户信息
 */
@Test
public void user_update() {
	try {
		Class.forName("com.mysql.jdbc.Driver");
		Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0203", "root", "root");
		String sql="UPDATE users SET username=? ,userpwd=? WHERE uid=?";
		PreparedStatement ps = connection.prepareStatement(sql);
		ps.setObject(1, "李时珍");
		ps.setObject(2, "789");
		ps.setObject(3, 4);
		int row = ps.executeUpdate();
		System.out.println(row);
		ps.close();
		connection.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
	
}
/**
 * 增加一个用户
 */
@Test
public void  user_insert() {
	try {
		Class.forName("com.mysql.jdbc.Driver");
		Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0203", "root", "root");
		//创建增加的sql
		String sql="INSERT INTO users(username,userpwd)VALUES(?,?)";
		//创建预编译对象
		PreparedStatement ps = connection.prepareStatement(sql);
		//替换占位符的值
		ps.setObject(1, "李四");
		ps.setObject(2, "456");
		//执行sql
		int row = ps.executeUpdate();
		System.out.println(row);
		ps.close();
		connection.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

四.封装JDBC工具类

1.JDBC工具类封装
需求说明:
之前的CRUD(增删改查)代码中有一些重复的代码,我们可以将他们抽取出来封装成工具类。
封装的思想可以简化代码开发,提高代码的复用性,提高开发的效率。
补充知识点:
在这里插入图片描述

Propertis类实现了Map接口,也就是可以使用map接口的API。
获取数据:String getProperty(String key, String defaultValue)
存储数据:Object setProperty(String key, String value)
加载文件中的数据:load()

在这里插入图片描述

封装的思路:
1、创建配置文件:jdbc.propertie
2、编写JDBC工具类:JDBCTool
代码示例:
Jdbc.properties
创建一个properties文件,里面写以下内容:
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql:///mysql0203
mysql.user=root
mysql.password=root
工具类:JDBCTool

/**
 * JDBC工具类
 * @author admin
 *
 */
public class JDBCTool {

	//定义一个连接对象
	private static Connection connection=null;
	
	/**
	 * 加载配置文件中的数据,创建连接对象
	 */
	static {
		try {
			//创建加载配置文件的propertis对象
			Properties properties=new Properties();
			//加载配置
			properties.load(new FileInputStream(new File("src/jdbc.properties")));
			//获取配置文件中的参数
			String dirver = properties.getProperty("mysql.driver");
			String url = properties.getProperty("mysql.url");
			String user = properties.getProperty("mysql.user");
			String password = properties.getProperty("mysql.password");
			//加载JDBC驱动
			Class.forName(dirver);
			//创建连接对象
			 connection = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	/**
	 * 获取连接对象
	 */
	public static Connection getConnection() {
		return connection;
	}
	/**
	 * 关闭查询对象释放资源
	 */
	public static void closeQuery(Connection connection,
			Statement statement,ResultSet resultSet) {
		try {
			if (resultSet!=null) {
				resultSet.close();
			}
			if (statement!=null) {
				statement.close();
			}
			if (connection!=null) {
				connection.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 关闭增删改对象释放资源
	 */
	public static void closeUpdate(Connection connection,
			Statement statement) {
		try {
			
			if (statement!=null) {
				statement.close();
			}
			if (connection!=null) {
				connection.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
}

2.优化增删改查

	/**
	 * 增加用户
	 */
   @Test
   public void user_insert() {
	  
	   try {
		   //使用工具类创建连接对象
		   Connection connection = JDBCTool.getConnection();
		   //创建预编译对象
		   PreparedStatement ps = connection.prepareStatement("INSERT INTO users(username,userpwd)VALUES(?,?)");
		   ps.setObject(1, "翠花");
		   ps.setObject(2, "123456");
		   int row = ps.executeUpdate();
		   System.out.println(row);
		   //关闭对象
		   JDBCTool.closeUpdate(connection, ps);
	   } catch (SQLException e) {
			e.printStackTrace();
		}
   }

五、数据库连接池

5.1连接池概念原理
多线程:线程池?比如:共享单车 共享充电宝
目前操作数据库的图示:
在这里插入图片描述

这样的操作存在的问题:
1、数据库连接是一种关键的有限的昂贵的资源,传统数据库连接每发出一个请求都要创建一个 连接对象,使用完直接关闭不能重复利用;
2、关闭资源需要手动完成,一旦忘记会造成内存溢出;(内存泄漏和内存溢出)
3、请求过于频繁的时候,创建连接极其消耗内存;而且一旦高并发访问数据库,有可能会
造成系统崩溃。
解决方式:
使用连接池,连接池全称是 Database Connection Pool。

原理:
1、数据库连接池负责分配、管理和释放数据库连接,它的核心思想就是连接复用,
2、通过建立一 个数据库连接池,这个池中有若干个连接对象,当用户想要连接数据库,就要先从连接池中获取连接对象,然后操作数据库。
3、一旦连接池中的连接对象被用完了,判断连接对象的个数是否已达上限,如果没有可以再创建新的连接对象,
4、如果已达上限,用户必须处于等待状态, 等待其他用户释放连接对象,直到连接池中有被释放的连接对象了,这时候等待的用户才能获取连接对象,从而操作数据库。
5、这样就可以使连接池中的连接得到高效、安全的复用,避免了数据库连接频繁创建、关闭的开销。这项技术明显提高对数据库操作的性能。
连接池的优势:
(1)程序启动时提前创建好连接,不用用户请求时创建,给服务器减轻压力;
(2)连接关闭的时候不会直接销毁 connection,这样能够重复利用;
(3)如果超过设定的连接数量但是还没有达到最大值,那么可以再创建;
(4)如果空闲了,会默认销毁(释放)一些连接,让系统性能达到最优;

面试题:
内存泄漏和内存溢出的区别?(面试题)
内存溢出(out of memory):指程序在申请内存时,没有足够的内存空间供其使用,出现 out of memory,简单通俗理解就是内存不够用了,比如给了你一个储存int类型数据的内存空间,你缺用来存了long类型的数据,结果就会导致内存不够用,就会报错OOM(内存溢出)。
内存泄露(memory leak):指程序在申请内存后,无法释放已申请的内存空间,内存泄露堆积会导致内存被占光。借用别人的比喻就是:比如有10张纸,本来一人一张,画完自己擦了还回去,别人可以继续画,现在有个坏蛋要了纸不擦不还,然后还跑了找不到人了,如此就只剩下9张纸给别人用了,这样的人多起来后,最后大家一张纸都没有了。
两者关系:内存泄露 → 剩余内存不足 → 后续申请不到足够内存 →内存溢出memory leak 最终会导致 out of memory。
线程池和连接池的区别?(面试题)
连接池:
1、连接池是面向数据库连接的
2、连接池是为了优化数据库连接资源
3、连接池有点类似在客户端做优化
线程池:
1.、线程池是面向后台程序的
2、线程池是是为了提高内存和CPU效率
3、线程池有点类似于在服务端做优化

5.2自定义连接池
连接池技术可以分为两大类:
1)自定义连接池:自己或者团队需要的时候可以自己封装连接池
2)第三方连接池:目前市面上比较流行的连接池技术(推荐使用)

自定义连接池思路:
1、创建一个保存连接对象的容器或者叫池子
2、创建获取连接对象的方法
3、创建归还连接对象的方法
4、测试连接池

代码示例:

public class MyDataBasePool {

	//1、创建一个保存连接对象的容器或者叫池子
	private static List<Connection> poolList=new ArrayList<Connection>();
	//定义初始化连接数量
	private static int num=10;
	//创建若干连接对象,存储到连接池集合对象中
	static {
		for (int i = 0; i <num; i++) {
			try {
				Class.forName("com.mysql.jdbc.Driver");
				Connection connection = DriverManager.getConnection("jdbc:mysql:///mysql0203", "root", "root");
				//将连接对象存储到连接池集合中
				poolList.add(connection);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	//2、创建获取连接对象的方法
	
	public static Connection getConnection() {
		//从集合中获取一个连接对象
		Connection connection = poolList.get(0);
		System.out.println(connection);
		//将集合的元素移除
		poolList.remove(0);
		return connection;
	}
	//3、创建归还连接对象的方法
	public static void  returnConnection(ResultSet resultSet,
			Statement statement,Connection connection) {
		try {
			if (resultSet!=null) {
				resultSet.close();
			}
			if (statement!=null) {
				statement.close();
			}
			if (connection!=null) {
				System.out.println(connection);
				//将连接对象放回集合中
				poolList.add(connection);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}

CRUD测试
/**
	 * 自定义连接池测试
	 */
	@Test
	public void user_insert() {
		//创建连接对象
		Connection connection = MyDataBasePool.getConnection();
		String sql="INSERT INTO users(username,userpwd)VALUES(?,?)";
		try {
			PreparedStatement ps = connection.prepareStatement(sql);
			ps.setObject(1, "xiaohei");
			ps.setObject(2, "123456");
			int row = ps.executeUpdate();
			System.out.println(row);
			//归还连接
			MyDataBasePool.returnConnection(null, ps, connection);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}

5.3第三方连接池
1、概述
在 Java 中开源的常用的数据库连接池有以下几种 :
1)DBCP
DBCP 是一个依赖 Jakarta commons-pool 对象池机制的数据库连接池.DBCP 可以直接的在应用程序中使用,Tomcat 的数据源使用的就是 DBCP。
2)c3p0 (推荐)
c3p0 是一个开放源代码的 JDBC 连接池,它在 lib 目录中与 Hibernate 一起发布,包括了实
现 jdbc3 和 jdbc2 扩展规范说明的 Connection 和 Statement 池的 DataSources 对象。
3)Druid
阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一 个 ProxyDriver,一系列内置的 JDBC 组件库,一个 SQL Parser。支持所有 JDBC 兼容的数据 库,包括 Oracle、MySql、Derby、Postgresql、SQL
2、连接池常见的配置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、第三方连接池使用-DBCP
Dbcp连接池使用:
提供的资料
在这里插入图片描述

使用步骤:
1、导入jar到项目中
2、导入配置文件
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///mysql0203
username=root
password=root
3、编写工具类

/**
 * DBCP连接池工具类
 * @author admin
 *
 */
public class DBCPPool {

	//定义一个连接对象变量
	private static Connection connection=null;
	/**
	 * 加载dbcp.properties配置文件获取里面的参数
	 */
	static {
		try {
			Properties properties=new Properties();
			properties.load(new FileInputStream(new File("src/dbcp.properties")));
			//创建数据源对象
			DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
			//创建连接对象
			 connection = dataSource.getConnection();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	/**
	 * 获取连接对象的方法
	 */
	public static Connection getConnection() {
		return connection;
	}
}
4、测试CRUD

/**
	 * dbcp连接池测试
	 */
	@Test
	public void user_insert_dbcp() {
		//创建连接对象
		Connection connection = DBCPPool.getConnection();
		String sql="INSERT INTO users(username,userpwd)VALUES(?,?)";
		try {
			PreparedStatement ps = connection.prepareStatement(sql);
			ps.setObject(1, "cuihua");
			ps.setObject(2, "111111");
			int row = ps.executeUpdate();
			System.out.println(row);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}

4、第三方连接-c3p0
1、提供的资料
在这里插入图片描述

3、使用步骤
① 导入jar包
② 导入配置文件并修改
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///mysql0203?useUnicode=true&characterEncoding=utf-8
c3p0.user=root
c3p0.password=root
③ 封装工具类

/**
	 * 1.c3p0连接池使用注意事项:
	 * 配置文件必须放在src目录下
	 * 配置文件中的key不能改变
	 */
	//创建连接对象
	public static Connection getConnection() {
		//创建数据源对象
		ComboPooledDataSource dataSource = new ComboPooledDataSource();
		//创建连接对象
		Connection connection=null;
		try {
			connection = dataSource.getConnection();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return connection;
	}
④ 测试

/**
	 * c3p0连接池测试
	 */
	@Test
	public void user_insert_c3p0() {
		//创建连接对象
		Connection connection = C3p0Pool.getConnection();
		String sql="INSERT INTO users(username,userpwd)VALUES(?,?)";
		try {
			PreparedStatement ps = connection.prepareStatement(sql);
			ps.setObject(1, "关羽");
			ps.setObject(2, "111111");
			int row = ps.executeUpdate();
			System.out.println(row);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}

六.DBUTils工具类

1、概述

概念:
DBUTIls工具类,在原生的JDBC基础是进行二次封装的第三方工具类。
下载:
http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi
下载后的资料:
在这里插入图片描述

DBUTils工具类的核心API简介:
1、DBUTIls类:关闭连接对象
2、QueryRunner类:执行数据库的增删改查操作,这个类中提供了update()执行增删改操作,提供了query()方法执行查询操作。
3、ResultSetHandler接口:查询返回的结果集对象。将resultSet对象进行了二次的封装,提供了更加简介的查询结果对象。
2、DML操作实现
1)导入jar包
2)代码示例
dbutils+c3p0推荐使用的JDBC操作

	/**
	 * 修改用户
	 * 
	 */
	@Test
	public void user_update() {
		try {
			//1.创建queryRunner:需要数据源对象
			QueryRunner queryRunner=new QueryRunner(new ComboPooledDataSource());
			//2执行sql
			String sql="UPDATE users SET username=? ,userpwd=? WHERE uid=?";
			int row = queryRunner.update(sql, "张三丰","456789",10);
			System.out.println(row);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 增加用户
	 */
	@Test
	public void user_insert() {
		//1.创建QueryRunner对象:作用就相当于我们的statement和preparedStatement对象
		/**
		 * 1、使用无参构造创建的对象:后面执行增删改查的操作时候需要携带connection
		 * 2、使用有参构造创建对象:构造函数中需要数据源对象,执行增删改查的时候不需要携带connection
		 */
		QueryRunner queryRunner=new QueryRunner();
		//2执行目标sql
		/**
		 * queryrunner提供了增删改的方法:update()当使用的queryrunner对象是无参构造创建的时候需要携带connection
		 *                                                  查询方法:query()
		 */
		Connection connection = C3p0Pool.getConnection();
		String sql="INSERT INTO users(username,userpwd)VALUES(?,?)";
		try {
			// Object... params可变参数:0或者多个参数列表
			int row=queryRunner.update(connection,sql,"李四","789789");
			//3.处理返回的结果
			System.out.println(row);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}

3、DQL操作实现
DBUTIls封装的返回结果集ResultSetHandler有以下几种常用的实现类:
在这里插入图片描述

目前需要我们掌握的实现类:
1、BeanHandler 将查询的结果封装到一个javaBean对象中。通过返回的是一个结果对象。每个结果就是数据库表的一行数据。
2、BeanListHandler:将返回的结果封装到javaBean对象中然后在将对象封装到集合中,通常返回的是一个对象的结果集合。也就是对应的是数据库表的多行数据。
3、ScalarHandler:返回的是具体的一个整数,通常用在聚合查询中

知识点补充:javaBean
1)javaBean就是一个java类,类中所有的属性私有化,有set/get方法
2)一个javaBean对应数据库表的一张表
3)一个javaBean实例化对象对应表的一行数据
4)JavaBean属性名称对应数据库表的字段名称
5)JavaBean属性的数据类型和数据表的字段类型对应

代码示例:

/**
	 * 查询所有用户信息
	 */
	@Test
	public void user_all() {
		try {
			QueryRunner queryRunner=new QueryRunner(new ComboPooledDataSource());
			String sql="SELECT * FROM users";
			List<Users> list = queryRunner.query(sql, 
					new BeanListHandler<Users>(Users.class));
			for (Users users : list) {
				System.out.println(users);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	
	}
	
	/**
	 * 查询id=9的用户信息
	 */
	@Test
	public void user_getUser() {
		try {
			
			QueryRunner queryRunner=new QueryRunner(new ComboPooledDataSource());
			String sql="SELECT * FROM users WHERE uid=?";
			//List<Integer> list=new ArrayList<Integer>();
			//new BeanHandler<T>(type)相当于ResultSetHandler rs=new BeanHandler();
			//T数据表对应的java实体类类名type实体类的字节码对象
			Users users = queryRunner.query(sql, new BeanHandler<Users>(Users.class), 9);
			System.out.println(users);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

用户实体类:
public class Users {
	//属性名称类型必须和用户表字段名称类型一致
	private Integer uid;
	private String username;
	private String userpwd;
	
	
	public Users(Integer uid, String username, String userpwd) {
		super();
		this.uid = uid;
		this.username = username;
		this.userpwd = userpwd;
	}
	//DBUTIls必须满足实体类中有无参构造
	public Users() {
		super();
		// TODO Auto-generated constructor stub
	}
	//get/set方法
	public Integer getUid() {
		return uid;
	}
	public void setUid(Integer uid) {
		this.uid = uid;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getUserpwd() {
		return userpwd;
	}
	public void setUserpwd(String userpwd) {
		this.userpwd = userpwd;
	}
	@Override
	public String toString() {
		return "Users [uid=" + uid + ", username=" + username + ", userpwd=" + userpwd + "]";
	}				
}

以上是javaJDBC及CURD知识学习的一些总结归纳,供自己复习巩固使用的,有需要学习的小伙伴也可以看一看,也可以给出一些建议或者出错的地方也可以告诉我。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值