JDBC
JDBC是什么
JDBC全称:Java DataBase Connectivity ,表示Java数据库连接。
JDBC就是让Java与数据库连接起来,用Java进行操作数据库,管理数据库。
同时JDBC是数据库各大厂商和Java共同定制的,它是一套标准。能用来连接任何数据库,而不只是连接其中一种数据库。
为什么用JDBC
前面我们花了大篇幅说了JavaWeb的各种知识及工具,说到前端,servlet,数据库等等。我们说到Java要存取数据,可是数据要从哪来呢?从文件吗?不是,文件结构杂乱无章,很不方便存取数据。然后我们就说到了数据库,了解到数据库是根据数据结构来组织、存储、管理数据的仓库,知道数据库对数据操作管理很方便,所以我们最终选择了数据库,因为通过它可以很方便的存取数据,所以我们要存取数据库的数据,就必须要用Java连接数据库,那么也就必须得了解JDBC。
怎么用JDBC
以连接MySQL为例
第一步:引入Jar包:如mysql-connection-java-5.1.7-bin.jar
第二步:加载数据库驱动
Class.forName(“com.mysql.jdbc.Driver”);
请注意:如果是用于JavaSE可以省略此步骤,但是用于JavaWeb项目那就需要加载。
第三步:通过驱动管理器获取连接对象。
Connection conn = DriverManager.getConnection(“数据库连接地址”,“帐号”,“密码”);
// 数据库连接地址格式: 主协议:子协议://ip地址:端口号/数据库名称
// mysql的连接地址: jdbc:mysql://localhost:3306/java35
// oracle的连接地址: jdbc:oracle:thin:@localhost:1521:ORCL
第四步: 通过连接对象,创建预编译对象,预编译SQL语句
如:String sql = “update user set name = ? where id = ?”;
PrepareStatement pre = conn.prepareStatement(sql);
如果不需要填充参数,可以选择执行SQL对象:Statement对象。
第五步:如果sql语句有?号,那就需要填充参数。
如 : pre.setString(1,name);
pre.setString(2,id);
第六步:填充参数后再通过预编译对象执行SQL语句.
int i = pre.executeUpdate();
记住它有返回值,类型是整型,如果它的值大于0则执行成功,否则执行失败
第七步:释放资源
看自己在这些步骤中用到了哪些和数据库相关的对象。
如Connection(连接对象)、PrepareStatement(预编译对象、Statement(SQL执行对象)、ResultSet(结果集对象)
这些对象如果用到了都需要进行释放。
实战阶段
真的要用JDBC,我们需要想想用什么模式比较适合,最终目的是使代码低耦合,高复用。
而DAO模式就是一个很好的选择,DAO层是数据接口访问层,在业务逻辑层与数据库资源间起到桥梁的作用,DAO模式是标准的JavaEE设计模式之一,开发人员使用这个模式把底层的数据访问操作和上层的业务逻辑分开。
一个典型的DAO实现有下列几个组件:
一个DAO接口
一个DAO工厂类
至少一个DAO具体实现类
实体类
首先,我们需要创建一个实体类,这个实体类就是数据传递对象。当我们清楚要存取的是哪些数据的时候,根据这些数据的字段名和类型,封装成对象。
比如:
我知道当前要存取的数据是student表下的所有字段。
那就封装成这样:
package bean;
public class Student {
private String 学号;
private String 姓名;
private int 年龄;
private String 性别;
private String 专业;
public Student(String 学号, String 姓名, int 年龄, String 性别, String 专业) {
super();
this.学号 = 学号;
this.姓名 = 姓名;
this.年龄 = 年龄;
this.性别 = 性别;
this.专业 = 专业;
}
public Student() {
super();
}
public String get学号() {
return 学号;
}
public void set学号(String 学号) {
this.学号 = 学号;
}
public String get姓名() {
return 姓名;
}
public void set姓名(String 姓名) {
this.姓名 = 姓名;
}
public int get年龄() {
return 年龄;
}
public void set年龄(int 年龄) {
this.年龄 = 年龄;
}
public String get性别() {
return 性别;
}
public void set性别(String 性别) {
this.性别 = 性别;
}
public String get专业() {
return 专业;
}
public void set专业(String 专业) {
this.专业 = 专业;
}
}
接下来我们就开始创建DAO接口,我们需要知道DAO要实现哪些功能。根据一个具体的功能,创建一个方法。
如:
package dao;
import java.util.List;
import bean.Student;
public interface StudentDao {
//增删改查
//1.增:添加学生信息
int insertStudent(Student newStudent);
//2.删:删除学生信息
int deleteStudent(int id);
//3.改:修改学生信息
int updateStudent(int id,Student newStudent);
//4.查:查看所有学生信息
List<Student> selectStudent();
}
再然后我们就开始着手创建一个具体实现类,根据这些功能写出具体实现的代码。
如:
package dao.impl;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import bean.Student;
import dao.StudentDao;
public class StudentDaoImpl implements StudentDao{
@Override
public int insertStudent(Student newStudent) {
//1. 通过驱动管理器, 获取JDBC连接对象.
Connection conn = null;
PreparedStatement pre = null;
int i = 0;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qq","root","1234");
// 2. 通过连接对象, 创建SQL执行对象 (SQL执行环境)
String sql = "insert into student(学号,姓名,年龄,性别,专业) values (?,?,?,?,?)";
pre = conn.prepareStatement(sql);
// 3.填充参数
pre.setString(1, newStudent.get学号());
pre.setString(2, newStudent.get姓名());
pre.setInt(3, newStudent.get年龄());
pre.setString(4, newStudent.get性别());
pre.setString(5, newStudent.get专业());
//4. 通过SQL执行对象 ,执行SQL语句.
i = pre.executeUpdate();
}catch (SQLException e) {
e.printStackTrace();
}finally {
//5. 释放资源
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
pre.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return i;
}
@Override
public int deleteStudent(int id) {
//1. 通过驱动管理器, 获取JDBC连接对象.
Connection conn = null;
PreparedStatement pre = null;
int i = 0;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qq","root","1234");
// 2. 通过连接对象, 创建SQL执行对象 (SQL执行环境)
String sql = "delete from student where 学号 = ?";
pre = conn.prepareStatement(sql);
// 3.填充参数
//装箱成对象
Integer id1 = id;
//由整型对象转换为字符串
String id2 = id1.toString();
pre.setString(1, id2);
//4. 通过SQL执行对象 ,执行SQL语句.
i = pre.executeUpdate();
}catch (SQLException e) {
e.printStackTrace();
}finally {
//5. 释放资源
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
pre.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return i;
}
@Override
public int updateStudent(int id, Student newStudent) {
//1. 通过驱动管理器, 获取JDBC连接对象.
Connection conn = null;
PreparedStatement pre = null;
int i = 0;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qq","root","1234");
// 2. 通过连接对象, 创建SQL执行对象 (SQL执行环境)
String sql = "update student set 学号=?,姓名=?,性别=?,年龄=?,专业=? where 学号 = ?";
pre = conn.prepareStatement(sql);
// 3.填充参数
pre.setString(1, newStudent.get学号());
pre.setString(2, newStudent.get姓名());
pre.setString(3, newStudent.get性别());
pre.setInt(4, newStudent.get年龄());
pre.setString(5, newStudent.get专业());
//装箱成对象
Integer id1 = id;
//由整型对象转换为字符串
String id2 = id1.toString();
pre.setString(6, id2);
//4. 通过SQL执行对象 ,执行SQL语句.
i = pre.executeUpdate();
}catch (SQLException e) {
e.printStackTrace();
}finally {
//5. 释放资源
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
pre.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return i;
}
@Override
public List<Student> selectStudent() {
//1. 通过驱动管理器, 获取JDBC连接对象.
List<Student> list = new ArrayList<Student>();
Connection conn = null;
PreparedStatement pre = null;
ResultSet rs =null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qq","root","1234");
// 2. 通过连接对象, 创建SQL执行对象 (SQL执行环境)
String sql = "select * from student";
pre = conn.prepareStatement(sql);
//3. 通过SQL执行对象 ,执行SQL语句.
rs = pre.executeQuery();
while(rs.next()) {
String 学号 = rs.getString(1);
String 姓名 = rs.getString(2);
int 年龄 = rs.getInt(3);
String 性别 = rs.getString(4);
String 专业 = rs.getString(5);
Student stu = new Student(学号, 姓名, 年龄, 性别, 专业);
list.add(stu);
}
}catch (SQLException e) {
e.printStackTrace();
}finally {
//5. 释放资源
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
pre.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return list;
}
}
之后你还可以再创建一个业务逻辑层的代码,包括接口与实现类,这步我就不写了,因为我只是做一个简单的实战,不涉及其他条件和逻辑了。
最后我们创建一个有main方法的类。看能够实现连接数据库,并显示数据库的信息。
如:
package test;
import java.util.List;
import bean.Student;
import dao.StudentDao;
import dao.impl.StudentDaoImpl;
public class Main {
public static void main(String[] args) {
StudentDao dao = new StudentDaoImpl();
List<Student> list = dao.selectStudent();
for (Student student : list) {
System.out.print("学号:"+student.get学号()+"\t");
System.out.print("姓名:"+student.get姓名()+"\t");
System.out.print("年龄:"+student.get年龄()+"\t");
System.out.print("性别:"+student.get性别()+"\t");
System.out.print("专业:"+student.get专业());
System.out.println(" ");
}
}
}
控制台显示如下:
好了,实战结束,同样我们也可以创建JavaWeb项目,把这些信息传送到html上,显示在网页里。都是可行的。
JDBC可以不必那么麻烦
大家或许看到我实战的代码比较多,好吧,我承认,其实我连接数据库是不会写这么多代码的,之所以写这么多,只是为了更好的了解JDBC,连接JDBC不必那么麻烦,因为我们有连接池。能更省事。
第一步:引入jar包
第二步:添加下列配置文件,这个配置文件大家可以保存
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 默认配置,只可以出现一次 -->
<default-config>
<property name="checkoutTimeout">1000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">2</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">5</property>
<property name="minPoolSize">2</property>
<property name="maxStatements">50</property>
<property name="acquireIncrement">3</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">
<![CDATA[jdbc:mysql://127.0.0.1:3306/auth?useUnicode=true&characterEncoding=UTF-8]]>
</property>
<property name="user">root</property>
<property name="password">123</property>
</default-config>
</c3p0-config>
只要修改下文件中的数据库地址以及账户密码,就行了。
第三步:复制网上的c3po连接池工具类就好了,自己去搜索,网上有。
比如我复制的:
package com.t.util;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class MyC3P0Test{
private static DataSource dataSource = new ComboPooledDataSource();
//封装一个方法,让别人能够获取连接池中的连接
public static Connection getConnetion()throws Exception{
return dataSource.getConnection();
}
public static void closeAll(ResultSet rs, Statement stat, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();// 连接池已经重写类该方法,该方法是将连接重新放回到连接池
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
这个工具类其实就是把我们的获取连接方法,和释放资源方法给封装了,因为每次我们只要获取连接对象时,都要写很长的一段代码,包括数据库地址、账户和密码,还有就是每次都有处理异常的释放资源方法。这样每次要实现具体功能要进行连接数据库时,直接调用工具类即可,就比较省事。
第四步:自己测试一下看能够连接成功,连接成功就根据JDBC步骤来。
如测试:
package com.t.util;
import java.sql.Connection;
public class Test {
public static void main(String[] args) throws Exception {
Connection date = MyC3P0Test.getConnetion();
System.out.println(date);
}
}
当显示了这么一长串地址时,说明连接成功。