JDBC(Java DataBase Connectivity, Java数据库连接) ,是一种用于执行SQL语句的Java API,为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。有了JDBC,程序员只需用JDBC API写一个程序,就可访问所有数据库。
SUN公司是规范制定者,制定了规范JDBC(连接数据库规范)
DriverManager类
作用:管理各种不同的JDBC驱动
Connection接口
Statement接口和PreparedStatement接口
ResultSet接口
数据库厂商微软、甲骨文等分别提供实现JDBC接口的驱动jar包 程序员学习JDBC规范来应用这些jar包里的类。
加载一个Driver驱动
创建数据库连接(Connection)
创建SQL命令发送器Statement
通过Statement发送SQL命令并得到结果
处理结果(select语句)
关闭数据库资源ResultSet Statement Connection
使用反射加载驱动,其实就是获得一个类的字节码,在获得类的字节码的过程中,一定会加载类进入内存,一旦进入内存会执行代码中的静态代码块,一执行代码块,就会自动的向DriverManager中注册一个驱动
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
mysql8 之前的数据库驱动名 com.mysql.jdbc.Driver
mysql8 开始的数据库驱动 com.mysql.cj.jdbc.Driver
url 同一资源定位符
协议 jdbc:mysql:
ip地址 127.0.0.1/localhost
url 同一资源定位符
端口号 3306
具体的资源路径 mydb
mysql8之前: jdbc:mysql://127.0.0.1:3306/mydb
mysql8开始: jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
useSSL=false 不使用SSL加密机制
&useUnicode=true 使用unicode字符集
&characterEncoding=utf8 使用utf8作为通信字符集
&serverTimezone=Asia/Shanghai 确定时区为 Asia/Shanghai
其中的mydb指的是数据库名,可以根据需求修改
public static void insert(){
Connection connection = null;
Statement statement = null;
try {
//1:加载一个Driver驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2:创建数据库连接(Connection)
String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String uid = "root"; //账号
String pwd = "root"; //密码
connection = DriverManager.getConnection(url,uid,pwd);
//创建SQL命令发送器
statement = connection.createStatement();
// 向数据库发送语句 数据库执行完毕后 返回参数
int n = statement.executeUpdate("insert into student values('689845','黄贵根','656972','信息工程学院',666)");
if(n > 0){
System.out.println("数据添加成功!");
}else{
System.out.println("数据添加失败!");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally{
//关闭处理
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
从上述代码中不难发现,仅仅只是实现添加这么一个操作,就需要如此多的代码,细想,如果要写多个增删改的操作,难道每次都要写这么多行的代码嘛?
所以一般到了这个时候,我们就需要一个工具类,来简化。
public class DBUtil {
//数据库的连接的静态方法
public static Connection getConnection(){
String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String uid = "root"; //账号
String pwd = "root"; //密码
Connection connection = null;
Statement statement = null;
//1:加载一个Driver驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection(url,uid,pwd);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return connection;
}
//关闭处理
public static void CloseAll(Connection connection, Statement statement, ResultSet resultSet){
//关闭处理
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public static void insert(){
Connection connection = null;
Statement statement = null;
try {
connection = DBUtil.getConnection();
//创建SQL命令发送器
statement = connection.createStatement();
// 向数据库发送语句 数据库执行完毕后 返回参数
int n = statement.executeUpdate("insert into student values('689845','黄贵根','656972','信息工程学院',666)");
if(n > 0){
System.out.println("数据添加成功!");
}else{
System.out.println("数据添加失败!");
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.CloseAll(connection,statement,null);
}
}
这样子添加看似好像没问题,而且也已经很简化了,可是再想想,假如我要换一个表,或者说我不想添加操作了,我要修改或者删除。怎么办?重复写不麻烦嘛?所以这个时候,我们就需要扩展一下DBUtil工具类了
public static int executeUpdate(String sql,Object [] params) {
Connection conn = null;
PreparedStatement pstmt = null;
int n = 0;//添加失败
try {
//2.建立和数据库的连接
conn = getConnection();
//3.创建一个SQL命令发送器
pstmt = conn.prepareStatement(sql);
//4.准备好SQL语句,通过SQL命令发送器发送给数据库,并得到结果
for (int i = 0; i <params.length ; i++) {
pstmt.setObject(i+1, params[i]);
}
n = pstmt.executeUpdate();
//System.out.println(n);
} catch (SQLException e) {
e.printStackTrace();
} finally {
//6.关闭资源
CloseAll(conn,pstmt,null);
}
return n;
}
这个时候我们再添加数据,实际上只需要三行代码就可以实现了,即使是换了个数据库表或者其他操作,也无需重复写代码
public static void InsertPlus(){
//三行代码即可完成
String sql = "insert into student value(?,?,?,?,?)";
Object []objects = {
"689845","黄贵根","656972","信息工程学院",666.0};
int n = DBUtil.executeUpdate(sql,objects);
if(n > 0){
System.out.println("数据添加成功!");
}else{
System.out.println("数据添加失败!");
}
}
删除行不行呢?试试呗~
String sql = "delete from student where realname = ?";
Object []objects = {
"黄贵根"};
int n = DBUtil.executeUpdate(sql,objects);
原因:没有添加jar包或者com.mysql.jdbc2.Driver路径错误
url错误
原因:用户名或者密码错误
原因:主键冲突
public class Student {
private String son; //学号
private String realname; //姓名
private String password; //密码
private String classname; //院系
private Double score; //总成绩
}
public static List<Student> FindAll(){
Connection connection = DBUtil.getConnection();
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
//创建List集合来接收数据
List<Student> list = new ArrayList<>();
try {
preparedStatement = connection.prepareStatement("select * from student where classname = ?");
//1表示第一个占位符,也就是?。 而不是数据库里面的第几个字段
preparedStatement.setString(1,"信息工程学院");
//接收结果
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
//后面对应的是数据库里面的字段名
String son = resultSet.getString("son");
String realname = resultSet.getString("realname");
String password = resultSet.getString("password");
String classname = resultSet.getString("classname");
Double score = resultSet.getDouble("score");
//存到实体类
Student student = new Student(son,realname,password,classname,score);
//存到集合
list.add(student);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
public static void main(String[] args) {
//测试
List<Student> list = FindAll();
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
这个时候我们发现,每个数据库里面的字段,都要定义一个相应的变量来接收,这么做很不方便。怎么办呢?那我们就来扩展一下DBUtil工具类吧。
public static <T> List<T> baseQuery(T t, String sql, Object ... args){
// 获取list集合中要装的对象的字节码
Class aClass = t.getClass();
Connection connection = null;
PreparedStatement statement = null;
ResultSet set = null;
List<T> list = null;
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement(sql);
// 设置参数的过程
for (int i = 0; i < args.length; i++) {
statement.setObject(i + 1, args[i]);
}
set = statement.executeQuery();
// 获取全部的字段
Field[] fs = aClass.getDeclaredFields();
// 先设置属性可以访问
for(Field f:fs){
f.setAccessible(true);
}
list=new ArrayList<>();
while(set.next()){
// 创建对象
T element = (T)aClass.newInstance();
// 从结果集的一条数据中取出每个字段的信息,放入element对象上去
// 遍历fs 通过属性名 去结果集中获取数据
for(Field f:fs){
String name = f.getName();
Object value=null;
// 判断实体类属性的数据类型,选择对应的get方法
if(f.getType()==int.class){
value = set.getInt(name);
}else if(f.getType()==double.class){
value = set.getDouble(name);
}else if(f.getType()==boolean.class){
value = set.getBoolean(name);
}else{
value= set.getObject(name);
}
f.set(element,value);
}
list.add(element);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
CloseAll(connection,statement,set);
}
return list;
}
有了这个工具类之后,我们几乎只需要一行代码,就可以兼容多种查询的操作方法
public static void FindAllPlus(){
//查询所有信息工程学院的学生
String sql = "select * from student where classname = ?";
//这个时候几乎一行代码就可以完成操作
List<Student> list = DBUtil.baseQuery(new Student(),sql,"信息工程学院");
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
怎么样?是不是简化好多了~
public class DBUtil {
//数据库的连接的静态方法
public static Connection getConnection(){
String url="jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String uid = "root"; //账号
String pwd = "root"; //密码
Connection connection = null;
Statement statement = null;
//1:加载一个Driver驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection(url,uid,pwd);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return connection;
}
//关闭处理
public static void CloseAll(Connection connection, Statement statement, ResultSet resultSet){
//关闭处理
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static int executeUpdate(String sql,Object [] params) {
Connection conn = null;
PreparedStatement pstmt = null;
int n = 0;//添加失败
try {
//2.建立和数据库的连接
conn = getConnection();
//3.创建一个SQL命令发送器
pstmt = conn.prepareStatement(sql);
//4.准备好SQL语句,通过SQL命令发送器发送给数据库,并得到结果
for (int i = 0; i <params.length ; i++) {
pstmt.setObject(i+1, params[i]);
}
n = pstmt.executeUpdate();
//System.out.println(n);
} catch (SQLException e) {
e.printStackTrace();
} finally {
//6.关闭资源
CloseAll(conn,pstmt,null);
}
return n;
}
public static <T> List<T> baseQuery(T t, String sql, Object ... args){
// 获取list集合中要装的对象的字节码
Class aClass = t.getClass();
Connection connection = null;
PreparedStatement statement = null;
ResultSet set = null;
List<T> list = null;
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement(sql);
// 设置参数的过程
for (int i = 0; i < args.length; i++) {
statement.setObject(i + 1, args[i]);
}
set = statement.executeQuery();
// 获取全部的字段
Field[] fs = aClass.getDeclaredFields();
// 先设置属性可以访问
for(Field f:fs){
f.setAccessible(true);
}
list=new ArrayList<>();
while(set.next()){
// 创建对象
T element = (T)aClass.newInstance();
// 从结果集的一条数据中取出每个字段的信息,放入element对象上去
// 遍历fs 通过属性名 去结果集中获取数据
for(Field f:fs){
String name = f.getName();
Object value=null;
// 判断实体类属性的数据类型,选择对应的get方法
if(f.getType()==int.class){
value = set.getInt(name);
}else if(f.getType()==double.class){
value = set.getDouble(name);
}else if(f.getType()==boolean.class){
value = set.getBoolean(name);
}else{
value= set.getObject(name);
}
f.set(element,value);
}
list.add(element);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
CloseAll(connection,statement,set);
}
return list;
}
}
public static List<Student> FindAllPlus(){
//查询所有信息工程学院的学生
String sql = "select * from student where classname = ?";
//这个时候几乎一行代码就可以完成操作
List<Student> list = DBUtil.baseQuery(new Student(),sql,"信息工程学院");
return list;
}
public static void InsertPlus(){
//三行代码即可完成
String sql = "insert into student value(?,?,?,?,?)";
Object []objects = {
"689845","黄贵根","656972","信息工程学院",666.0};
int n = DBUtil.executeUpdate(sql,objects);
}
然而即使如此,我们未来将还会有更优质的解决方案可以使用,这就等我们接下来学Mybatis之后就知道了。下期再见~