博客
关于我
JDBC最简单的数据库连接方式,不会给你一jio!!!
阅读量:692 次
发布时间:2019-03-17

本文共 24084 字,大约阅读时间需要 80 分钟。



利用Java语言连接数据库的技术,JDBC是最基本的连接方式,当然以后接触到框架之后,就会有很多其他的简单方式,但是从上学开始,引用老师说的最多的一句话就是:“万变不离其宗”.首先就是应该掌握最基本的连接方式!!!

使用Java语言连接数据库的时候,最愉快的方式大概就是下图所示!!!

在这里插入图片描述



一、JDBC概述


1、什么是JDBC

JDBC(Java Database Connectivity) Java数据库连接;

其实就是利用Java语言/程序连接并访问数据库的一门技术;

之前我们可以通过CMD或者navicat等工具连接数据库;

但在企业开发中,更多的是通过程序(Java程序)连接并访问数据库,通过Java程序访问数据库,就需要用到JDBC这门技术。

在这里插入图片描述

2、如何通过JDBC程序访问数据库

  • (1) 提出需求:

创建一个 jt_db 数据库,在库中创建一个account表,并插入三条记录,然后利用Java程序查询出account表中所有的记录,并将查询的结果打印在控制台上。

  • (2) 开发步骤:

① 准备数据, 创建jt_db库, 创建account表10

drop database if exists jt_db;create database jt_db charset utf8;    use jt_db;    create table account(    id int primary key auto_increment,    name varchar(50),    money double);insert into account values(null, 'tom', 1000);insert into account values(null, 'andy', 1000);insert into account values(null, 'tony', 1000);

数据是随机添加,如果已经有其他的测试表,此步骤可以跳过;

② 创建JAVA工程:

在这里插入图片描述

③ 导入jar包 ---- mysql驱动包

在这里插入图片描述

④ 创建类并实现JDBC程序(六个步骤)
在这里插入图片描述

  • 注册数据库驱动
  • 获取数据库连接
  • 获取传感器
  • 发送SQL到服务器并返回执行结果
  • 处理结果
  • 释放资源

代码实现:

package cn.tedu.jdbc;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;/* * 查询jt_db库中account表中的所有记录 */public class Test_JDBC1 {   	public static void main(String[] args) throws Exception {   		//1.注册数据库驱动		Class.forName("com.mysql.jdbc.Driver");		//2.获取数据库链接		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8", "root", "root");		//3.获取传感器		Statement stat = conn.createStatement();		//4.基于传输器发送SQL语句到服务器执行,返回执行结果		String sql = "select * from account";		ResultSet rs = stat.executeQuery(sql);		//5.处理结果(打印到控制台)		while (rs.next()) {   			int id = rs.getInt("id");			String name = rs.getString("name");			double money = rs.getDouble("money");			System.out.println(id + "," + name + "," + money);		}		//6.释放资源(释放资源倒序释放) -- 越晚获取越先关闭		rs.close();		stat.close();		conn.close();//		System.out.println("Test_JDBC01.main()...");	}}

执行结果:

在这里插入图片描述

3、JDBC API 总结

(1) 注册数据库驱动

  • Class.forName("com.mysql.jdbc.Driver");
  • 所谓的注册驱动,就是让JDBC程序加载mysql驱动程序,并管理驱动;
  • 驱动程序实现了JDBC API定义的接口以及和数据库服务器交互的功能,加载驱动是为了方便使用这些功能;

(2) 获取连接之数据库URL

Connection conn = DriverManager.getConnection(    "jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8",    "root", "root" );
  • DriverManager.getConnection() 用于获取数据连接,返回的Connection连接对象是JDBC程序连接数据库至关重要的一个对象。

  • 参数2参数3分别是所连接数据库的用户名和密码(根据自己的数据库用户名和密码去写)

  • 参数1jdbc:mysql://localhost:3306/jt_db 是连接数据库的URL,用于指定访问哪一个位置上的数据库服务器及服务器中的哪一个数据库,其写法为:

在这里插入图片描述

  • 当连接本地数据库,并且端口为3306时,可以简写
  • 简写形式为如下形式:
jdbc:mysql:///jt_db

(3) Statement传输器对象

Statement stat = conn.createStatement();//该方法返回用于向数据库服务器发送sql语句的Statement传输器对象
  • 该对象上提供了发送sql的方法:
executeQuery(String sql) 用于向数据库发送【查询】类型的sql语句,返回一个ResultSet对象中executeUpdate(String sql) 用于向数据库发送【更新(增加、删除、修改)】类型的sql语句,返回一个int值,表示影响的记录行数

(4) ResultSet结果集对象

  • ResultSet对象用于封装sql语句查询的结果,也是一个非常重要的对象。
  • 该对象上提供了遍历数据及获取数据的方法。
  1. 遍历数据行的方法

next() – 使指向数据行的箭头向下移动一行,并返回一个布尔类型的结果,true表示箭头指向了一行数据,false表示箭头没有指向任何数据(后面也没有数据了)

  1. 获取数据的方法
getInt(int columnIndex)getInt(String columnLable)getString(int columnIndex)getString(String columnLable)getDouble(int columnIndex)getDouble(String columnLable)getObject(int columnIndex)getObject(String columnLable)

(5) 释放资源

rs.close();stat.close();conn.close();
  • 此处释放资源必须按照一定的顺序释放,越晚获取的越先关闭 ---- (倒序关闭)

  • 所以先关闭rs对象,再关闭stat对象,最后关闭conn对象。

  • 除此之外,为了避免上面的程序抛出异常,释放资源的代码不会执行,应该把释放资源的代码放在finally块中.

try{   	...}catch(Exception e){   	...}finally{       if (rs != null) {           try {           	rs.close();        } catch (SQLException e) {               e.printStackTrace();        } finally {               rs = null;        }    }    if (stat != null) {           try {           	stat.close();        } catch (SQLException e) {               e.printStackTrace();        } finally {               stat = null;        }    }    if (conn != null) {           try {           	conn.close();        } catch (SQLException e) {               e.printStackTrace();        } finally {               conn = null;        }    }}

修改之后的全部代码:

package cn.tedu.jdbc;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;/* * 查询jt_db库中account表中的所有记录 */public class Test_JDBC2 {   	public static void main(String[] args) {   		Connection conn = null;		Statement stat = null;		ResultSet rs = null;		try {   			//1.注册数据库驱动			Class.forName("com.mysql.jdbc.Driver");			//2.获取数据库链接			conn = DriverManager.getConnection("jdbc:mysql:///jt_db?characterEncoding=utf-8", "root", "root");			//3.获取传输器			stat = conn.createStatement();			//4.基于传输器发送SQL语句到服务器执行,返回执行结果			String sql = "select * from account";			rs = stat.executeQuery(sql);					//5.处理结果(打印到控制台)			while (rs.next()) {   				int id = rs.getInt("id");				String name = rs.getString("name");				double money = rs.getDouble("money");				System.out.println(id + "," + name + "," + money);			}		} catch (Exception e) {   			e.printStackTrace();//打印异常信息		} finally {   //finally代码块中的代码块一定会执行			//6.释放资源(释放资源倒序释放) -- 越晚获取越先关闭			if (rs != null) {   //如果rs为null.直接跳过,不执行代码块					try {   					rs.close();				} catch (SQLException e) {   					e.printStackTrace();				}finally {   					rs = null;				}			}			if (stat != null) {   								try {   					stat.close();				} catch (SQLException e) {   					e.printStackTrace();				}finally {   					stat = null;				}			}			if (conn != null) {   								try {   					conn.close();				} catch (SQLException e) {   					e.printStackTrace();				}finally {   					conn = null;				}			}		}	}}

二、JDBC增删改查


package com.tedu.jdbc02;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;import org.junit.Test;import com.tedu.util.JdbcUtil;public class TestJdbc03 {   	private Statement stat;		/* 新增:往account表中添加一个名称为john、money为3500的记录 */	@Test	public void testAdd(){   		Connection conn = null;		Statement stat = null;		ResultSet rs = null;		try {   			//注册驱动并获取连接			Class.forName("com.mysql.jdbc.Driver");			conn = DriverManager.getConnection("jdbc:mysql://localhost/jt_db?characterEncoding=utf-8", "root", "root");						//获取传输器并执行SQL,返回执行结果			stat = conn.createStatement();			String sql = "insert into account value(null,'john',3500)";			int rows = stat.executeUpdate(sql);						//处理结果			System.out.println("影响行数" + rows);					} catch (Exception e) {   			e.printStackTrace();//打印异常		}finally {   			//释放资源			JdbcUtil.close(conn, stat, rs);		}	}		/* 修改:将account表中名称为john的记录,money修改为1500 */	@Test	public void testUpdate() {   		Connection conn = null;		Statement stat = null;		ResultSet rs = null;		try {   			//注册驱动并获取连接			conn = JdbcUtil.getConn();						//获取传输器并执行SQL语句,返回执行结果			stat = conn.createStatement();			String sql = "update account set money = 1500 where name = 'john'";			int rows = stat.executeUpdate(sql);			System.out.println("打印行数" + rows); 					} catch (Exception e) {   			e.printStackTrace();		}finally {   			//释放资源			JdbcUtil.close(conn, stat, rs);		}	}		/* 删除:删除account表中名称为john的记录 */	@Test	public void testDelete() {   		Connection conn = null;		Statement stat = null;		ResultSet rs = null;		try {   			conn = JdbcUtil.getConn();			stat = conn.createStatement();			String sql = "delete from account where name ='john'";			int rows = stat.executeUpdate(sql);			System.out.println("影响行数" + rows);		} catch (Exception e) {   			e.printStackTrace();		}finally {   			//释放资源			JdbcUtil.close(conn, stat, rs);		}	}		/* 查询:查询account表中id为1的记录 */	@Test	public void testFindById() {   		Connection conn = null;		Statement stat = null;		ResultSet rs = null;		try {   			conn = JdbcUtil.getConn();			stat = conn.createStatement();			String sql = "select * from account where id = 1";			rs = stat.executeQuery(sql);			//处理结果			if( rs.next() ) {   				int id = rs.getInt("id");				String name = rs.getString("name");				double money = rs.getDouble("money");				System.out.println( id+" : "+name+" : "+money);			}		} catch (Exception e) {   			e.printStackTrace();		}finally {   			//释放资源			JdbcUtil.close(conn, stat, rs);		}	}}

执行结果:(执行顺序自己总结)

在这里插入图片描述


三、PreparedStatement


在上面的增删改查的操作中,使用的是Statement传输器对象,而在开发中我们用的更多的传输器对象是PreparedStatement对象,PreparedStatement是Statement的子接口,比Statement更加安全,并且能够提高程序执行的效率。

Statement父对象

PreparedStatement子对象

1、模拟用户登录案例

  • (1) 准备数据
use jt_db;create table user(    id int primary key auto_increment,    username varchar(50),    password varchar(50));insert into user values(null,'张三','123');insert into user values(null,'李四','234');
  • 因为连接数据库和释放资源的代码是重复的,所以封装成一个方法
package com.tedu.util;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class JdbcUtil {   		/**	 * 获取注册驱动并获取连接对象(默认连接的库是jt_db,用户名密码都是root)	 * @return 连接对象	 */	public static Connection getConn() {   		Connection conn = null;		try {   			//注册驱动并获取连接			Class.forName("com.mysql.jdbc.Driver");			conn = DriverManager.getConnection("jdbc:mysql://localhost/jt_db?characterEncoding=utf-8", "root", "root");			return conn;		} catch (Exception e) {   			e.printStackTrace();		}		return conn;	}		/**	 * 方法重载:注册驱动并获取连接对象	 * @param db 连接的数据库名字	 * @param user 数据库的用户名用户名	 * @param pwd 数据库的密码	 * @return 连接对象	 */	public static Connection getConn(String db,String user,String pwd) {   		Connection conn = null;		try {   			//注册驱动并获取连接			Class.forName("com.mysql.jdbc.Driver");			conn = DriverManager.getConnection("jdbc:mysql://localhost/"+db+"?characterEncoding=utf-8", user, pwd);			return conn;		} catch (Exception e) {   			e.printStackTrace();		}		return conn;	}			/**	 * 释放JDBC程序中的资源	 * @param conn 连接对象	 * @param stat 传输器对象	 * @param rs 结果集对象	 */	static public void close(Connection conn,Statement stat,ResultSet rs) {   		//6.释放资源(释放资源倒序释放) -- 越晚获取越先关闭		if (rs != null) {   //如果rs为null.直接跳过,不执行代码块				try {   				rs.close();			} catch (SQLException e) {   				e.printStackTrace();			}finally {   				rs = null;			}		}		if (stat != null) {   							try {   				stat.close();			} catch (SQLException e) {   				e.printStackTrace();			}finally {   				stat = null;			}		}		if (conn != null) {   							try {   				conn.close();			} catch (SQLException e) {   				e.printStackTrace();			}finally {   				conn = null;			}		}	}}
  • (2) 创建LoginUser 类,提供 main 方法 和 login 方法。
package com.tedu.ps;import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;import java.util.Scanner;import com.tedu.util.JdbcUtil;/** * 模拟用户登录 * @author Administrator *	存在SQL注入攻击缺陷 */public class LoginUser {   	public static void main(String[] args) {   		Scanner sc = new Scanner(System.in);		//1.提示用户登录		System.out.println("请登录!!!");				//2.提示用户输入用户名并接收用户名		System.out.println("请输入用户名...");		String user = sc.nextLine();				//3.提示用户输入密码并接收密码		System.out.println("请输入密码...");		String pwd = sc.nextLine();				//4.调用login方法,将用户名和密码传入,进行登录		login(user ,pwd);	}	/**	 * 根据用户名和密码进行登录	 * @param user 用户名	 * @param pwd 密码	 */	private static void login(String user, String pwd) {   		Connection conn = null;		Statement stat = null;		ResultSet rs = null;		try {   			//1.注册驱动并获取连接			conn = JdbcUtil.getConn();			//2.获取传输器,执行SQL,返回执行结果			stat = conn.createStatement();			String sql = "select * from user where username = '"+user+"' and password = '"+pwd+"'";			System.out.println(sql);			rs = stat.executeQuery(sql);						//处理结果			if (rs.next()) {   //true 如果返回true,则用户名密码正确,允许登录				System.out.println("恭喜您登录成功!!!");			}else {   //false,没有数据,则用户名或密码不正确,登录失败				System.out.println("登录失败!!用户名或密码不正确");			}					} catch (Exception e) {   			e.printStackTrace();		}finally {   			//释放资源			JdbcUtil.close(conn, stat, rs);		}	}}

2、SQL注入攻击

  • 执行时,输入:
请登录:请输入用户名:张飞'#'请输入密码:select * from user where username='张飞'#'' and password=''恭喜您登录成功了!
  • 或输入
请登录:请输入用户名:张飞' or '1=1请输入密码:select * from user where username='张飞' or '1=1' and password=''恭喜您登录成功了!
  • 或输入
请登录:请输入用户名:请输入密码:' or '2=2select * from user where username='' and password='' or '2=2'恭喜您登录成功了!

通过上面的案例,我们发现在执行时,不输入密码只输入用户名也可以登陆成功。这就是SQL注入攻击。

  • SQL注入攻击产生的原因: 由于后台执行的SQL语句是拼接而来的:
select * from user where username='"+user+"' and password='"+pwd+"'

其中的参数是用户提交过来的,如果用户在提交参数时,在参数中掺杂了一些SQL关键字(比如or)或者特殊符号(#、-- 、’ 等),就可能会导致SQL语句语义的变化,从而执行一些意外的操作(用户名或密码不正确也能登录成功)!

3、防止SQL注入攻击

如何防止SQL注入攻击?

  • (1) 使用正则表达式对用户提交的参数进行校验。如果参数中有(# – ’ or等)这些符号就直接结束程序,通知用户输入的参数不合法

  • (2) 使用PreparedStatement对象来替代Statement对象。

个人喜欢第二种方式,下面通过第二种方式解决SQL注入攻击:添加loginByPreparedSatement方法,在方法中,使用PreparedStatement来代替Statement作为传输器对象使用,代码示例:

package com.tedu.ps;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.Statement;import java.util.Scanner;import org.junit.Test;import com.tedu.util.JdbcUtil;/** * 模拟用户登录 * @author Administrator *	存在SQL注入攻击缺陷 */public class LoginUser2 {   	private static ResultSet rs;	public static void main(String[] args) {   		Scanner sc = new Scanner(System.in);		//1.提示用户登录		System.out.println("请登录!!!");				//2.提示用户输入用户名并接收用户名		System.out.println("请输入用户名...");		String user = sc.nextLine();				//3.提示用户输入密码并接收密码		System.out.println("请输入密码...");		String pwd = sc.nextLine();				//4.调用login方法,将用户名和密码传入,进行登录		login(user ,pwd);	}	/**	 * 根据用户名和密码进行登录	 * @param user 用户名	 * @param pwd 密码	 */	private static void login(String user, String pwd) {   		Connection conn = null;//		Statement stat = null;		PreparedStatement ps = null;		ResultSet rs = null;		try {   			//1.注册驱动并获取连接			conn = JdbcUtil.getConn();			//2.获取传输器,执行SQL,返回执行结果			//-- ? 就是占位符			String sql = "select * from user where username = ? and password = ?";			//将sql(骨架)传给服务器编译并确定下来(一旦变异之后,就不能再被改变)			ps= conn.prepareStatement(sql);						//设置SQL语句中的参数			ps.setString(1, user);			ps.setString(2, pwd);						//执行SQL语句			rs = ps.executeQuery();//不要再次传入SQL语句,上面已经传过了						//处理结果			if (rs.next()) {   //true 如果返回true,则用户名密码正确,允许登录				System.out.println("恭喜您登录成功!!!");			}else {   //false,没有数据,则用户名或密码不正确,登录失败				System.out.println("登录失败!!用户名或密码不正确");			}					} catch (Exception e) {   			e.printStackTrace();		}finally {   			//释放资源			JdbcUtil.close(conn, ps, rs);		}	}		/** 使用prepareStatment传输器查询所有用户 */	@Test	public void testFindAll() {   		Connection conn = null;		PreparedStatement ps = null;		ResultSet rs = null;		try {   			//1.注册驱动并获取连接			conn = JdbcUtil.getConn();			//2.获取传输器,执行SQL,返回执行结果			String sql = "select * from user";			//将sql(骨架)传给服务器编译并确定下来(一旦变异之后,就不能再被改变)			ps= conn.prepareStatement(sql);			//执行SQL语句			rs = ps.executeQuery();//不要再传SQL语句						while (rs.next()) {   				int id = rs.getInt("id");				String username = rs.getString("username");				String password = rs.getString("password");				System.out.println(id +":"+ username +":"+ password);			}					} catch (Exception e) {   			e.printStackTrace();		}finally {   			//释放资源			JdbcUtil.close(conn, ps, rs);		}	}}

再次执行程序,按照上面的操作登录。此时,已经成功的防止了SQL注入攻击问题了。

PreparedStatement对象是如何防止SQL注入攻击的:

使用PreparedStatement对象是先将SQL语句的骨架发送给服务器编译,编译之后SQL语句的骨架和语义就不会再被改变了,再将SQL语句中的参数发送给服务器,即使参数中再包含SQL关键字或者特殊符号,也不会导致SQL的骨架或语义被改变,只会被当作普通的文本来处理!


  • 使用PreparedStatement对象可以防止SQL注入攻击

  • 而且通过方法设置参数更加的方便且不易出错!

  • 还可以从某些方面提高程序执行的效率!

4、Junit单元测试

加了@Test注解的方法,可以通过单元测试(junit)框架测试该方法。底层会创建该方法所在类的实例,通过实例调用该方法

@Testpublic void testInsert() {   	System.out.println("TestPreparedStatement.testInsert()");}

导包之后项目底下大概是这样的:(可能是JUnit4也可能是JUnit5,看你导入的哪个)

在这里插入图片描述
能够使用@Test单元测试测试的方法必须满足如下几个条件:

(1)方法必须是公共的(2)方法必须是非静态的(3)方法必须是无返回值的(4)方法必须是无参数的(5)进行单元测试的方法或者类命名时不要命名为Test/test

四、数据库连接池(数据源)


1、什么是连接池

池:指内存中的一片空间(容器,比如数组、集合)

连接池:就是将连接存放在容器中,供整个程序共享,可以实现连接的复用,减少连接创建和关闭的次数,从而提高程序执行的效率!

在这里插入图片描述

2、为什么要使用连接池

2.1 传统方式操作数据库

在这里插入图片描述

Connection conn = DriverManager.getConnection( url, user, pwd ); //创建连接对象conn.close(); //关闭连接, 销毁连接

在传统方式中,每次用户需要连接访问数据库时,都是创建一个连接对象,基于这个连接对象访问数据库,用完连接后,会将连接关闭(conn.close)。

由于每次创建连接和关闭连接非常的耗时间,而且耗资源,因此会导致程序执行的效率低下。

2.2 使用连接池操作数据库

在这里插入图片描述

可以在程序一启动时,就创建一批连接放在一个连接池中(容器),当用户需要连接时,就从连接池中获取一个连接对象,用完连接后,不要关闭,而是将连接再还回连接池中,这样一来,用来用去都是池中的这一批连接,实现了连接的复用,减少了连接创建和关闭的次数,从而提高了程序执行的效率!

3、如何使用C3P0连接池

dbcp/c3p0/druid

使用C3P0连接池开发步骤:

3.1 导入开发包

在工程底下新建一个lib文件夹,把jar文件复制进去,然后选中jar文件
右键 —>Build Path —> Add to Build Path
然后就可以看到Referenced Libraries
在这里插入图片描述
3.2 创建数据库连接池(对象)

ComboPooledDataSource pool = new ComboPooledDataSource();

3.3 设置连接数据库的基本信息

  • (1) 方式一:(不推荐) 直接将参数通过 pool.setXxx方法设置给c3p0程序

这种方式直接将参数写死在了程序中,后期一旦参数发生变化,就要修改程序,要重新编译项目、重新发布项目,非常麻烦。

//设置连接数据库的基本信息pool.setDriverClass( "com.mysql.jdbc.Driver" );pool.setJdbcUrl( "jdbc:mysql:///jt_db?characterEncoding=utf-8" );pool.setUser( "root" );pool.setPassword( "root" );
  • (2) 方式二:将连接参数提取到properties文件中(推荐)

  • 文件必须放在src(源码根目录)目录下!!!

  • 文件名必须叫做c3p0.properties

  • 在类目录下(开发时可以放在src或者类似的源码目录下),添加一个c3p0.properties文件,配置内容如下:

c3p0.driverClass = com.mysql.jdbc.Driverc3p0.jdbcUrl = jdbc:mysql:///jt_db?characterEncoding=utf-8c3p0.user = rootc3p0.password = root

在这里插入图片描述

这种方式由于是c3p0到指定的位置下寻找指定名称的properties文件,所以文件的位置必须是放在src或其他源码根目录下,文件名必须是c3p0.properties。

  • (3) 方式三:(推荐)

在类目录下(开发时可以放在src或者类似的源码目录下),添加一个c3p0-config.xml文件,配置内容如下:

com.mysql.jdbc.Driver
jdbc:mysql:///jt_db?characterEncoding=utf-8
root
root

这种方式由于是c3p0到指定的位置下寻找指定名称的xml文件,所以文件的位置必须是放在src或其他源码根目录下,文件名必须是c3p0-config.xml。

3.4 从连接池中获取一个连接对象并进行使用

Connection conn = pool.getConnection();

3.5 用完连接后将连接还回连接池中

JdbcUtil.*close*(conn, ps, rs);/* 如果是自己创建的连接对象,这个连接对象没有经过任何的改动,调用* conn.close方法,是将连接对象关闭* 如果是从连接池中获取的连接对象,该连接对象在返回时就已经被连接池* 改造了,将连接对象的close方法改为了还连接到连接池中*/

测试代码:

package com.tedu.c3p0;import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;import org.junit.Test;import com.mchange.v2.c3p0.ComboPooledDataSource;import com.tedu.util.JdbcUtil;public class TestC3P0 {   		/** 使用c3p0查询account表中的所有数据 */	@Test	public void testFindAll() {   		Connection conn = null;		Statement stat = null;		ResultSet rs = null;				//获取一个连接池对象(获取存放连接的容器/池子)		ComboPooledDataSource pool = new ComboPooledDataSource();								try {   						//设置链接数据库的基本信息(driver/url/user/pwd,三种方式)			//方式一:(不推荐)//			pool.setDriverClass("com.mysql.jdbc.Driver");//			pool.setJdbcUrl("jdbc:mysql:///jt_db?characterEncoding=utf-8");//			pool.setUser("root");//			pool.setPassword("root");						//c3p0程序会到类目录下找c3p0.properties文件或者c3p0-config.xml文件			//从连接池中获取一个连接对象,进行使用			conn = pool.getConnection();			//不需要引入,它会自动寻找c3p0-config.xml文件,或者c3p0.properties文件					stat = conn.createStatement();			String sql = "select * from account";			rs = stat.executeQuery(sql);						while (rs.next()) {   				int id = rs.getInt("id");				String name = rs.getString("name");				double money = rs.getDouble("money");				System.out.println(id +":"+ name +":"+ money);			}		} catch (Exception e) {   			e.printStackTrace();		}finally {   			/* 如果是自己创建的连接对象,这个连接对象没有经过任何的改动,调用			* conn.close方法,是将连接对象关闭			* 如果是从连接池中获取的连接对象,该连接对象在返回时就已经被连接池			* 改造了,将连接对象的close方法改为了还连接到连接池中			*/			JdbcUtil.close(conn, stat, rs);		}	}}

五、扩展:修改默认编码


1、切换新的工作空间,设置工作空间编码为utf-8

  • (1) 切换到新的工作空间目的:
    若旧的工作空间内容过多,可能会导致eclipse不编译,甚至进入休眠状态。
  • (2) 设置工作空间编码为utf-8,此后在当前工作空间下创建的项目编码也默认是utf-8。

在这里插入图片描述

2、设置JSP文件的编码为utf-8

在这里插入图片描述


六、JDBC实现学生管理系统


1、准备数据

建库建表语句如下:

-- 1、创建数据库jt_db数据库(如果不存在才创建)create database if not exists jt_db charset utf8;use jt_db; -- 选择jt_db数据库-- 2、在 jt_db 库中创建 stu 表(学生表)drop table if exists stu;create table stu(    id int,    name varchar(50),    gender char(2),    addr varchar(50),    score double);-- 3、往 stu 表中, 插入记录insert into stu values(1001,'张三','男', '北京', 86);

2、功能实现

运行程序控制台提示如下:

在这里插入图片描述

  • 输入a:查询所有学生信息
  • 输入b:添加学生信息
  • 输入c:根据id修改学生信息
  • 输入d:根据id删除学生信息

3、查询所有学生信息

在控制台中输入操作代码"a",效果如下:

在这里插入图片描述

4、添加学生信息

在控制台中输入操作代码"b",效果如下:

在这里插入图片描述

5、根据ID修改学生信息

在控制台中输入操作代码"c",效果如下:

在这里插入图片描述

6、根据ID删除学生信息

在控制台中输入操作代码"d",效果如下:

在这里插入图片描述
演示代码:

① 创建StudentManager.java

package com.tedu;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.Scanner;import com.tedu.util.JdbcUtil;/** * 学生信息管理系统 * 运行程序,根据选项,可以对学生信息进行增删改查操作。 */public class StudentManager {   	private static Scanner sc = new Scanner(System.in);		public static void main(String[] args) {   		while (true) {   			//1.提示选择操作选项			System.out.print("a:查询学生信息  ");			System.out.print("b:添加学生信息  ");			System.out.print("c:修改学生信息  ");			System.out.println("d:删除学生信息");			System.out.print("请输入操作,abcd任选一项:");			String opt = sc.next();			//2.根据选项执行不同操作			if( "a".equalsIgnoreCase( opt ) ){   				findAll(); //查询学生信息			}else if( "b".equalsIgnoreCase( opt ) ){   				addStu(); //添加学生信息			}else if( "c".equalsIgnoreCase( opt ) ){   				updateStu(); //修改学生信息			}else if( "d".equalsIgnoreCase( opt ) ){   				deleteStu(); //删除学生信息			}else{   				System.out.println("输入错误,请重新输入!");			}		}	}		/** a. 查询所有学生信息 */	private static void findAll() {   		Connection conn = null;		PreparedStatement ps = null;		ResultSet rs = null;		try {   			conn = JdbcUtil.getConn();			String sql = "select * from stu";			ps = conn.prepareStatement(sql);			rs = ps.executeQuery();			while(rs.next()){   				int id = rs.getInt("id");				String name = rs.getString("name");				String gender = rs.getString("gender");				String addr = rs.getString("addr");				double score = rs.getDouble("score");				System.out.println( id+","+name+","+gender						+","+addr+","+score );			}			System.out.println("-----------------");		} catch (Exception e) {   			e.printStackTrace();		}	}		/** b. 添加学生信息 */	private static void addStu() {   		System.out.println("请输入要添加的学生编号、姓名、性别、地址、成绩(使用空格分隔):");		int id = sc.nextInt();		String name = sc.next();		String gender = sc.next();		String addr = sc.next();		double score = sc.nextDouble();		Connection conn = null;		PreparedStatement ps = null;		ResultSet rs = null;		try {   			conn = JdbcUtil.getConn();			String sql = "insert into stu values(?,?,?,?,?)";			ps = conn.prepareStatement(sql);			ps.setInt(1, id);			ps.setString(2, name);			ps.setString(3, gender);			ps.setString(4, addr);			ps.setDouble(5, score);			int rows = ps.executeUpdate();			if (rows > 0) {   				System.out.println("添加成功!");			}		} catch (Exception e) {   			e.printStackTrace();		}	}		/** c. 根据id修改学生信息 */	private static void updateStu() {   		System.out.println("请输入要修改的学生编号、姓名、性别、地址、成绩(使用空格分隔):");		int id = sc.nextInt();		String name = sc.next();		String gender = sc.next();		String addr = sc.next();		double score = sc.nextDouble();		Connection conn = null;		PreparedStatement ps = null;		ResultSet rs = null;		try {   			conn = JdbcUtil.getConn();			String sql = "update stu set name=?,gender=?"					+ ",addr=?,score=? where id=?";			ps = conn.prepareStatement(sql);			ps.setString(1, name);			ps.setString(2, gender);			ps.setString(3, addr);			ps.setDouble(4, score);			ps.setInt(5, id);			int rows = ps.executeUpdate();			if (rows > 0) {   				System.out.println("修改成功!");			}		} catch (Exception e) {   			e.printStackTrace();		}	}		/** d. 根据id删除学生信息 */	private static void deleteStu() {   		System.out.println("请输入要删除的学生编号:");		int id = sc.nextInt();		Connection conn = null;		PreparedStatement ps = null;		ResultSet rs = null;		try {   			conn = JdbcUtil.getConn();			String sql = "delete from stu where id=?";			ps = conn.prepareStatement(sql);			ps.setInt(1, id);			int rows = ps.executeUpdate();			if (rows > 0) {   				System.out.println("删除成功!");			}		} catch (Exception e) {   			e.printStackTrace();		}	}}

② 创建JdbcUtil.java

package com.tedu.util;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;/** JDBC工具类 */public class JdbcUtil {   	/**	 * 获取数据库连接对象并返回	 * @return Connection对象	 * @throws Exception 	 */	public static Connection getConn() throws Exception{   		//1.注册驱动		Class.forName( "com.mysql.jdbc.Driver" );		//2.获取连接		Connection conn = DriverManager.getConnection(				"jdbc:mysql:///jt_db?characterEncoding=utf-8", 				"root", 				"root");		return conn;	}		/**	 * 释放JDBC程序中的资源	 * @param conn 连接对象	 * @param stat 传输器对象	 * @param rs 结果集对象	 */	public static void close(Connection conn, 			Statement stat, ResultSet rs){   		if(rs != null){   			try {   				rs.close();			} catch (SQLException e) {   				e.printStackTrace();			} finally{   				rs = null;			}		}		if(stat != null){   			try {   				stat.close();			} catch (SQLException e) {   				e.printStackTrace();			} finally{   				stat = null;			}		}		if(conn != null){   			try {   				conn.close();			} catch (SQLException e) {   				e.printStackTrace();			} finally{   				conn = null;			}		}	}}

这就是学生管理系统的代码,可以自己尝试测试,多动手尝试!!!

(ง •_•)ง



下篇文章介绍一部分简单的前端基础知识,包括HTML、CSS、JavaScript等!!!

让我们一起期待兔八哥的新分享吧.

ヾ(◍°∇°◍)ノ゙

在这里插入图片描述

转载地址:http://fvwhz.baihongyu.com/

你可能感兴趣的文章
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>
Mysql InnoDB存储引擎中的checkpoint技术
查看>>
Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
查看>>
MySQL InnoDB引擎的锁机制详解
查看>>
Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
查看>>
mysql InnoDB数据存储引擎 的B+树索引原理
查看>>
mysql innodb通过使用mvcc来实现可重复读
查看>>
mysql insert update 同时执行_MySQL进阶三板斧(三)看清“触发器 (Trigger)”的真实面目...
查看>>
mysql interval显示条件值_MySQL INTERVAL关键字可以使用哪些不同的单位值?
查看>>
Mysql join原理
查看>>
MySQL Join算法与调优白皮书(二)
查看>>
Mysql order by与limit混用陷阱
查看>>
Mysql order by与limit混用陷阱
查看>>
mysql order by多个字段排序
查看>>
MySQL Order By实现原理分析和Filesort优化
查看>>
mysql problems
查看>>
mysql replace first,MySQL中处理各种重复的一些方法
查看>>
MySQL replace函数替换字符串语句的用法(mysql字符串替换)
查看>>
mysql replace用法
查看>>