Java程序想要访问数据库,操作数据库,需要使用到一个技术:jdbc技术!
不管是我要讲的项目中用到的DbUtils还是SSM框架中的MyBatis,底层都必须使用jdbc,只不过代码的书写方式产生了变化!
那么什么是jdbc呢???
Java database connectivi2ty java的数据库连接,使用jdbc,java程序才能去操作数据库!
Jdbc本质上就是一个接口规范,在其中声明了访问数据库时的操作方法等!Java程序能够连接的数据库,不只是MySQL管理的,还可以是Oracle、SQLServer管理的!

所以,想要通过java代码操作数据库,我们需要首先将访问的数据库的管理厂商提供的驱动导入到工程中去!
原生jdbc的代码操作:
1、注册驱动
2、获取数据库连接
3、获取执行语句的平台对象
4、执行sql语句
5、处理结果
6、释放资源
贼固定,贼清晰!!!
示例代码:
/*
以添加数据,讲解原生jdbc操作的六大步骤
*/
public static void insertDemo() throws ClassNotFoundException, SQLException {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取数据库连接
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/doubleseven"
, "root", "123");
//3、获取执行语句的平台对象
Statement stat = connection.createStatement();
//4、执行sql语句
int row =
stat.executeUpdate("insert into student values (null, '阿飞', '男', '147')");
//5、处理结果
System.out.println(row > 0 ? "添加成功" : "添加失败");
//6、释放资源
stat.close();
connection.close();
}
//查询数据
public static void selectDemo() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/doubleseven",
"root", "123");
Statement stat = connection.createStatement();
/*
只要是执行的sql语句是查询的sql语句,调用的方法是executeQuery方法!
返回值为ResultSet结果集,查询的内容都存放在这个结果集中
所以,我们如果想要获取到查询出来的数据,我们只需要对这个结果集进行遍历即可!
*/
ResultSet set = stat.executeQuery("select * from student");
//只要set.next()为true,就代表还有未取出的结果集数据,就执行循环体,取出查询结果
//声明一个List集合来存储得到的所有学生
List<Student> list = new ArrayList<Student>();
while (set.next()) {
/*
在每一次遍历中,我们只需要获取到这一条记录中的字段值即可!
*/
int sid = set.getInt("sid");
String sname = set.getString("sname");
String gender = set.getString("gender");
String phone = set.getString("phone");
//构建学生对象,将从表中获取到的数据,以属性值的方式存入对象
Student student = new Student(sid, sname, gender, phone);
list.add(student);
}
for (Student student : list) {
System.out.println(student);
}
set.close();
stat.close();
connection.close();
}原生jdbc的操作出现了两个比较棘手的问题:
1、数据库连接对象Connection不断的创建与销毁是很占用内存的,利用率不高,程序性能比较低下,尤其是并发访问量过大时,程序容易崩溃!
2、查询结果集在封装成实体类对象时,是一件比较恶心的事情,太过复杂!但是封装又是势在必行的一件事情!因为我们程序内,最常用的与数据库的交互就是查询数据!
为了解决查询结果集封装以及sql语句执行的复杂,引入一个jdbc的工具类:DbUtils,这个第三方工具,完美的解决了原生jdbc中的复杂操作,尤其是查询操作!
使用DbUtils的步骤:
1、注册驱动
2、获取数据库连接对象
3、获取执行sql语句的QueryRunner对象
4、使用QueryRunner对象调用方法,传递sql语句,操作数据库
5、处理结果
6、释放资源
示例代码:
/*
以添加数据为例,讲解DbUtils的使用
*/
public static void insertDemo() throws ClassNotFoundException, SQLException {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取数据库连接对象
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/doubleseven",
"root", "123");
//3、获取执行sql语句的QueryRunner对象
QueryRunner qRunner = new QueryRunner();
//4、使用QueryRunner对象调用方法,传递sql语句,操作数据库
/*
原生jdbc中,增删改调用的是executeUpdate方法
使用DbUtils,增删改调用的是update方法,返回值依旧是整型数字,代表影响的行数
记住两个方法:
(1)、传入连接对象、传入sql语句
(2)、传入连接对象、传入sql语句、传入可变参数
当你的sql语句中,数据的来源是不确定的,我们可以在书写sql语句时,使用?来表示,那么我们就需要传递参数来为?绑定值!
如果书写的sql语句中没有不确定的值,那么就不需要传递参数绑定数据!
使用?绑定数据,除了能够适应于动态数据的传入,还能有效的防止sql注入的问题!!!
sql注入:就是传入的内容中包含了某些sql语句的关键字,从而影响了整个sql语句的语义,导致最终的结果出现偏差!!!
用户表:username password
zhangsan 123
select * from user where username = zhangsan or 1 = 1 and password = 1234567890;
zhangsan or 1 = 1
*/
//qRunner.update(connection, "insert into student values (null, '浩飞', '男', '166')");
int row = qRunner.update(connection, "insert into student values (null, ?, ?, ?)",
"刘博", "男", "188");
//5、处理结果
System.out.println(row > 0 ? "添加成功" : "添加失败");
//6、释放资源
DbUtils.close(connection);
}
/*
使用DbUtils完成查询操作
*/
public static void selectDemo() throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/doubleseven",
"root", "123");
QueryRunner qRunner = new QueryRunner();
/*
如果执行的sql语句是查询sql,那么此时调用的方法为query()方法!
连接对象、sql语句、结果集对象
连接对象、sql语句、结果集对象、可变参数
查询的sql语句,肯定会得到结果集,那么DbUtils针对不同的查询结果集设计了八大封装的结果集对象
用于封装不同的sql语句得到的不同结果!!!
常用的结果集对象,只需要记住三个:
BeanHandler,将查询结果集中的第一条记录封装到指定的JavaBean中
sql语句中的查询条件只能获取到唯一的一条记录时,使用此结果集对象!
BeanListHandler,将查询结果集中的每一条记录都封装成JavaBean,并将这些JavaBean对象放入List集合中
ScalarHandler,专门用于封装聚合函数得到的结果,也就是查询的结果为单一的数据
*/
/*
Student.class,学生类的对象,传入到BeanHandler()结果集的构造方法中,做了哪些事情???
1、找到了Student类中的无参构造方法,创建了学生对象
2、找到了对应属性的setter方法,完成了属性的赋值,为了能够保证赋值成功,属性名必须与表中的字段名一致!!!
*/
Student student = qRunner.query(connection, "select * from student where sid = 4",
new BeanHandler<Student>(Student.class));
System.out.println(student);
List<Student> stus = qRunner.query(connection, "select * from student",
new BeanListHandler<Student>(Student.class));
for (Student stu : stus) {
System.out.println(stu);
}
/*
Object count = qRunner.query(connection, "select count(*) from student",
new ScalarHandler());
System.out.println(count);*/
DbUtils.close(connection);
}针对数据库连接对象不断的创建、销毁导致的内存浪费问题,我们的解决方案是使用数据库连接池技术!

数据库连接池技术,在java程序中,有三个比较常用:c3p0、dbcp、druid
个人建议:如果从代码性能角度出发,建议使用druid或者dbcp
如果代码的简洁性角度出发,建议使用c3p0,但是其有个毛病,就是效率比较低
1、导入连接池的包
2、将连接信息放置在druid.properties文件中

3、连接池对象在jdbc操作时,用数据源DataSource来表示,所以我们应当获取到druid数据库连接池对应的数据源对象!

创建Druid数据源时,需要指定一个属性文件对象,因为要为数据源中的数据库连接对象设置连接信息!所以先通过输入流读取到druid.properties配置文件中的连接信息,然后将读取到的信息加载到属性文件对象中,进而传递到创建数据源的方法中!那么此时得到的数据源对象中的连接对象就具备了连接信息!
DbUtils+Druid完成数据库操作的示例代码:public static void updateDemo() throws SQLException {
/*
使用数据库连接池,只是改变了连接对象的获取方式,提升了程序的性能!与DbUtils的操作代码是无关的!
现在无需再手动获取、创建连接对象了,因为我们现在已经拿到了Druid的数据源,我们就可以从数据源中获取到连接池
管理的连接对象了!
这是使用DbUtils+Druid的第一种形式,手动从数据源中获取连接对象使用!
*/
//获取数据源
DataSource dataSource = DruidUtils.getDataSource();
//从数据源中获取连接对象
Connection connection = dataSource.getConnection();
//创建QueryRunner对象
QueryRunner qRunner = new QueryRunner();
//执行sql语句
int row = qRunner.update(connection, "update student set phone = ? where sid = ?",
"155", 3);
//处理结果
System.out.println(row > 0 ? "修改成功" : "修改失败");
//释放资源
/*
如果此时的连接对象是从数据源中获取到的,在执行释放资源的方法时,不是将其销毁,而是归还池子
*/
DbUtils.close(connection);
}
public static void selectDemo() throws SQLException {
/*
使用DbUtils+Druid的第二种形式,我们无需手动从数据源中获取连接对象
只需要在QueryRunner对象创建时,传递数据源作为参数,即可自动去数据源中获取连接!
而且此时在操作完数据库之后,也不需要释放资源,因为会自动将获取到的连接归还池子!
*/
//创建QueryRunner对象,指定数据源
QueryRunner qRunner = new QueryRunner(DruidUtils.getDataSource());
//执行sql语句,此时因为连接对象是自动获取的,所以方法的参数中不需要再传递连接对象Connection
List<Student> stus =
qRunner.query("select * from student", new BeanListHandler<Student>(Student.class));
for (Student student : stus) {
System.out.println(student);
}
}
















