JDBC的建立步骤

JDBC

Java Database Connectivity,简称JDBC,是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法

驱动程序:数据库厂商根据JDBC标准实现的数据库访问驱动,驱动类一般在com.mysql.cj.jdbc.Driver中,提供了创建驱动的方法

连接步骤:

  1. 加载驱动:Class.forName("com.mysql.cj.jdbc.Driver");
  2. 创建连接对象Connection,使用url,username,password连接数据库DriverManager.getConnection(url, "root", "123456");

默认URL格式:

String url="jdbc:mysql://localhost:3306/数据库名?useSSL=false&characterEncoding=utf8&serverTimezone=UTC";

Localhost:3306是访问mysql服务的ip:端口号,serverTimezone是时间

  1. 创建执行对象:Statement ,使用Statement sta=con.createStatement(); 

4、执行select语句,执行对象的executeQuery可以执行select语句,executeUpdate可以执行增删改操作

返回一个ResultSet结果集,

注意!ResultSet继承了 Wrapper, AutoCloseable接口,并没有继承Set接口,因此不是个集合

5、处理返回结果:

ResultSet提供了next方法,将行指针指向下一行,并返回是否有下一行,处理第一条数据前要先执行next方法。

提供了 getString(index) 和getString(“rowName”)两种方法读取数据,返回一个字符串

代码:

String sql="select s_id,s_name,s_sex from student";

ResultSet rs=sta.executeQuery(sql);

6、释放资源:

释放连接对象

连接释放顺序:按照资源生成顺序的倒序释放

依次释放ResultSet  Statement   Connection

使用close关闭,注意要判断is null ,虽然这三个类关闭都会抛出SQLException,但抛出异常要分开处理,否则中途抛出异常可能导致连接无法全部关闭

代码:if(rs!=null)

try {

rs.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

if(sta!=null)

{

try {

sta.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

if(con!=null)

{

try {

con.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

完整代码:

package jdbc.com.easy.jdbc;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class Easy {

public static void main(String[] args) {

try {

//--1 加载驱动

Class.forName("com.mysql.cj.jdbc.Driver");

//--2 创建链接

String url="jdbc:mysql://localhost:3306/sqydb?useSSL=false&characterEncoding=utf8&serverTimezone=UTC";

Connection con=DriverManager.getConnection(url, "root", "123456");

//--3 创建执行对象

Statement sta=con.createStatement();

//--4 执行sql语句

//executeUpdate 增删改 executeQuery 查询语句

String sql="select s_id,s_name,s_sex from student";

ResultSet rs=sta.executeQuery(sql);

//--5 解析执行结果

String s_id;

String s_name;

String s_sex;

while(rs.next())

{

//s_id=rs.getString(1);使用字段位置(列下标)获取,下标初始是1

s_id=rs.getString("s_id");

s_name=rs.getString("s_name");

s_sex=rs.getString("s_sex");

System.out.println(s_id+"    "+s_name+"   "+s_sex);

}

//-- 6 释放资源

rs.close();

sta.close();

con.close();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

使用配置文件+解析查询结果的方法创建数据库连接:

优点:可以将代码封装,数据库表对应的Class类放在约定文件夹中,除配置文件之外不需要对代码部分进行修改,代码可重入性高。

约定优于配置(convention over configuration),也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数量,获得简单的好处,而又不失灵活性。

可以使用单例模式设计类,构造方法私有化,安全可靠,节省空间。

对于数据库内的数据,都抽象为对象存储,符合面向对象的编程原则,对数据的操作更方便。

第一步:创建配置文件jdbc.properties,放在项目路径的约定包下,如properties包下

在properties包下,创建file文件,修改文件名为jdbc.properties

这里的propeties文件里存的是键值对,可以使用键找到值,形式为: 键=值,这里的键值默认是string类型,不需要加双引号

填入以下信息

driver_class_name=com.mysql.cj.jdbc.Driver

url=jdbc:mysql://localhost:3306/sqydb?useSSL=false&characterEncoding=utf8&serverTimezone=UTC

username=root

password=123456

第二步:

创建要查询的表对应的类,如要查询Student表,表中有四列,s_id,s_name,s_birth,s_sex

那么在对应的Student类中,也要有这四条同名属性,一定要同名,否则jdbc驱动不能解析

一般来说,数据对应类中的属性都封装为私有的,只能使用get,set方法进行操作

重写toString方法,方便查看数据,可以使用代码编辑器快速完成

package jdbc.com.easy.jdbc;

public class Student {

private String s_id;

private String s_name;

private String s_birth;

private String s_sex;

public String getS_id() {

return s_id;

}

public void setS_id(String s_id) {

this.s_id = s_id;

}

public String getS_name() {

return s_name;

}

public void setS_name(String s_name) {

this.s_name = s_name;

}

public String getS_birth() {

return s_birth;

}

public void setS_birth(String s_birth) {

this.s_birth = s_birth;

}

public String getS_sex() {

return s_sex;

}

public void setS_sex(String s_sex) {

this.s_sex = s_sex;

}

@Override

public String toString() {

return "Student [s_id=" + s_id + ", s_name=" + s_name + ", s_birth=" + s_birth + ", s_sex=" + s_sex + "]";

}

}

第三步:

使用单例模式创建JDBCUtil类,声明JDBC必须的类和配置文件中的属性,构造方法私有,提供getInstance方法获取唯一实例。

private Connection con=null;

private Statement sta=null;

private ResultSet rs=null;

private String driverClassName=null;

private String url=null;

private String username=null;

private String password=null;

private static JDBCUtil util=null;

//在静态代码块中使用懒汉式创建唯一的实例util

static {

try {

util=new JDBCUtil();

} catch (IOException e) {

e.printStackTrace();

}

}

//这里写构造方法,构造方法要对以上的属性进行赋值,就要读取配置文件,即使用文件输入流

private JDBCUtil() throws IOException

{

String

fileName=System.getProperty("user.dir")+"properties\\jdbc.properties";

//这里获取项目文件路径,是不带\\的,要自行加上,此外看一下你的配置文件是放在哪个目录下了,统一改到项目文件下的properties包下

//开始读配置文件,创建文件输入流,存到Properties类中,使用load(键)读取值

FileInputStream fis=new FileInputStream(fileName);

Properties p=new Properties();

p.load(fis);

// 读取配置文件中的四个值

driverClassName=p.getProperty("driver_class_name");

url=p.getProperty("url");

username=p.getProperty("username");

password=p.getProperty("password");

}

//既然是单例模式,那么从外面无法创建实例,要给出函数返回唯一实例util

public static JDBCUtil getInstance()

{

return util;

}

第四步:

开始建立连接,先加载驱动Driver(驱动是在主函数中加载的,使用Class.forName(类名)加载),再使用已经读取到的配置文件的信息,创建Connection连接

public Connection getConnection() throws ClassNotFoundException, SQLException

{

Class.forName(driverClassName);

if(con==null)

{

synchronized (this) {

if(con==null)

con=DriverManager.getConnection(url,username,password);

}

}

return con;

}

第五步:

创建执行对象Statement

这里的sta因为是全局变量,不要再次声明

public Statement getStatement() throws ClassNotFoundException, SQLException

{

if(con==null)

{

getConnection();

}

 sta=con.createStatement();

return sta;

}

第六步:

根据执行结果ResultSet,解析为表对应的类

这里类型若不确定,可以使用反射来确定类的类型,每个变量,即为变量填充数值

使用<T>泛型,来约束传入的类

public <T> T executeQuery(String sql,Class<T> clazz ) throws ClassNotFoundException, SQLException, IllegalArgumentException, IllegalAccessException, InstantiationException

{

if(sta==null)

getStatement();

rs= sta.executeQuery(sql);

//解析

//获取类中的属性

//Field是个数组,记录类中的变量,使用clazz.getDeclaredFields反射获取变量,因为这里的变量都是私有的,因此不能用getFields方法。获取变量列表后,可以使用迭代器来访问每一个变量,将变量值填入变量中,这时Student类还没有创建,因此要使用反射

Field[] fis= clazz.getDeclaredFields();

//从结果集中拿取指定数据设置到一个对象中,把对象返回

boolean hasNext=rs.next();

T t=clazz.newInstance();

//获取已经定义好的Students类的类型,当然可以换成其他类,取决于你定义的类

String value=null;

String fieldName=null;

if(hasNext)

//变量的填装

for(Field f:fis)

{

fieldName=f.getName();

f.setAccessible(true);

//先将private变量访问权限设为开放,将变量填装进指定的class中

f.set(t, rs.getString(fieldName));

}

//此时t即是表中的一条记录对应的类

return t;

}

第七步:

函数的调用,这一部分代码可以写在其他类中

public static void main(String[] args) {

JDBCUtil util=JDBCUtil.getInstance();

Student stu;

try {

//执行查询语句,这里的executeQuery是上面重写的方法,直接返回一个解析好的stu对象

stu = util.executeQuery("select * from student", Student.class);

System.out.println(stu.toString());

//到这里就结束了

} catch (ClassNotFoundException | IllegalArgumentException | IllegalAccessException | InstantiationException

| SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

完整代码:

package jdbc.com.easy.jdbc;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.lang.reflect.Field;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Properties;

import java.util.Set;

public class JDBCUtil {

private Connection con=null;

private Statement sta=null;

private ResultSet rs=null;

private String driverClassName=null;

private String url=null;

private String username=null;

private String password=null;

private static JDBCUtil util=null;

static {

try {

util=new JDBCUtil();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

private JDBCUtil() throws IOException

{

String fileName=System.getProperty("user.dir")+"\\properties\\jdbc.properties";

System.out.println(fileName);

FileInputStream fis=new FileInputStream(fileName);

Properties p=new Properties();

p.load(fis);

driverClassName=p.getProperty("driver_class_name");

url=p.getProperty("url");

username=p.getProperty("username");

password=p.getProperty("password");

}

/*

 * 获取当前类的实例

 */

public static JDBCUtil getInstance()

{

return util;

}

/*

 * 生成连接对象并返回

 */

public Connection getConnection() throws ClassNotFoundException, SQLException

{

Class.forName(driverClassName);

if(con==null)

{

synchronized (this) {

if(con==null)

con=DriverManager.getConnection(url,username,password);

}

}

return con;

}

/*

 * 生成执行对象并返回

 */

public Statement getStatement() throws ClassNotFoundException, SQLException

{

if(con==null)

{

getConnection();

}

 sta=con.createStatement();

return sta;

}

public <T> T executeQuery(String sql,Class<T> clazz ) throws ClassNotFoundException, SQLException, IllegalArgumentException, IllegalAccessException, InstantiationException

{

if(sta==null)

getStatement();

rs= sta.executeQuery(sql);

//解析

//获取类中的属性

Field[] fis= clazz.getDeclaredFields();

//从结果集中拿取指定数据设置到一个对象中,把对象返回

boolean hasNext=rs.next();

T t=clazz.newInstance();

String value=null;

String fieldName=null;

if(hasNext)

for(Field f:fis)

{

fieldName=f.getName();

f.setAccessible(true);

f.set(t, rs.getString(fieldName));

}

return t;

}

@Override

public String toString() {

return "JDBCUtil [con=" + con + ", sta=" + sta + ", rs=" + rs + ", driverClassName=" + driverClassName

+ ", url=" + url + ", username=" + username + ", password=" + password + "]";

}

JDBCUtil util=JDBCUtil.getInstance();

Student stu;

try {

stu = util.executeQuery("select * from student", Student.class);

System.out.println(stu.toString());

} catch (ClassNotFoundException | IllegalArgumentException | IllegalAccessException | InstantiationException

| SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值