连接前准备
创建配置文件,并将他设置为资源包
一、BaseConfig类
import java.sql.Connection;
import java.io.FileReader;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/***
* 自己创建一个文件夹存放数据库的配置信息:mysql.properties
*mysql.properties文件存放数据的配置信息
* 可以存放在工程的任意路径下,尽量离工程目录近一些
* 但是一定要将配置文件设置为Resources
* 因为在项目编译执行时,就会将Resources内的资源编译到classes的根目录下
*/
//读取配置信息类
public class BaseConfig {
/**
* 内部类,隐藏信息,
* 想要更换数据库可以直接在自己定义的properties配置文件中修改信息
* 更换数据库
*/
private class Config {
//配置信息
String driver;
String url;
String username;
String password;
//构造方法
public Config(String driver, String url, String username, String password) {
this.driver = driver;
this.url = url;
this.username = username;
this.password = password;
}
}
/**
* 使用Config做配置信息
* 将配置信息内的值(在properties配置文件中)通过文件流读取出来放到Config属性内(也就是class Config 的属性)
* Config属性就是上面的构造方法
* 在后面需要的时候直接调用
*/
private Config config;
{
try {
init();
//Class.forName(数据库驱动实现类),加载和注册数据库驱动
Class.forName(config.driver);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
//读取配置信息
private void init() throws Exception {
/**
Thread.currentThread():获取当前运行的线程
getContextClassLoader():获取当前线程的类加载器,在加载类的时侯读取配置信息
getResource:获取配置资源
getPath():获取路径
*/
String path = Thread.currentThread().getContextClassLoader()
.getResource("mysql.properties").getPath();
//文件流读取
Properties pro = new Properties();
//装载
pro.load(new FileReader(path));
//判断是否有url,其他三个属性可以有默认值
String url = pro.getProperty("url");
if (null == url) {
throw new Exception("url配置项缺失异常");
}
String driver = pro.getProperty("driver", "com.mysql.jdbc.Driver");
String username = pro.getProperty("username", "root");
String password = pro.getProperty("password", "root");
this.config = new Config(driver, url, username, password);
}
//Connection接口:一个连接对象,可用于创建 Statement 和 PreparedStatement 对象
//使用protected控制访问权限
protected Connection getCon() throws SQLException {
// DriverManager类: 1)管理和注册数据库驱动,2) 得到数据库连接对象
return DriverManager.getConnection(config.url, config.username
, config.password);
}
//关闭资源
protected void close(AutoCloseable... acs) {
for (AutoCloseable ac : acs) {
if (null != ac) {
try {
ac.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
二、BaseDao类
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public final class BaseDao extends BaseConfig {
//创建执行对象
private PreparedStatement getPst(Connection con, String sql, Object... params) throws SQLException {
//将sql查询语句拆分成字符串数组
//通过连接对象获得执行对象
PreparedStatement pst = con.prepareStatement(sql);
//由第三个参数获取sql语句的参数
if (params.length > 0) {
for (int i = 0; i < params.length; i++) {
pst.setObject(i + 1, params[i]);//params:动态参数
}
}
return pst;
}
public Result exeNonQuery(String sql, Object... params) {
Connection con = null;
PreparedStatement pst = null;
try {
con = getCon();
pst = getPst(con, sql, params);
return Result.succeed(pst.executeLargeUpdate());
//int executeUpdate()
//执行 DML,增删改的操作,返回影响的行数。
//ResultSet executeQuery()
// 执行 DQL,查询的操作,返回结果集
} catch (SQLException e) {
e.printStackTrace();
return Result.fail();
} finally {
close(pst, con);
}
}
public Result exeQuery(String sql, Object... params) {
Connection con = null;
PreparedStatement pst = null;
ResultSet rst = null;
try {
con = getCon();
//获取执行器,里面有连接信息,sql语句,以及sql语句的参数
pst = getPst(con, sql, params);
//使用执行对象执行sql语句,得到结果集
rst = pst.executeQuery();
//存放结果集
List<List<String>> data = new ArrayList<>();
//判断查询是否成功,并产生结果集
if (null != rst && rst.next()) {
/**
* 通过挂在结果集上的表结构信息获取获取行数
* getMetaData()获取表结构信息
* 因为每次查询的结过行数不会变化,定义为常量
*/
final int CC = rst.getMetaData().getColumnCount();
//外层循环提取行
do {
//创建数组时指定行数,优化数组的计算效率
List<String> row = new ArrayList<>(CC);
//内层循环提取列
for (int i = 1; i <= CC; i++) {
//行内添加列
row.add(rst.getObject(i).toString());
}
//表内添行
data.add(row);
} while (rst.next());
}
//查询成功,返回结果集
return Result.succeed(data);
} catch (SQLException e) {
//查询失败,调用Redult类的fail方法返回null
return Result.fail();
} finally {
close(rst, pst, con);
}
}
}
三、Result类
public final class Result<T> {
private boolean err;//错误属性,当当前属性值为true时,表示最终结果有问题
private T data;//数据属性:结果
public static <T> Result succeed(T data) {
//通过构造方法创建结果对象,并返回结果
return new Result(false, data);//错误属性位假,则查询结果通过,输出结果
}
public static Result fail() {
//通过构造方法创建结果对象,并返回结果
return new Result(true, null);//错误属性为真,则查询结果不通过,无结果
}
//构造方法
private Result(boolean err, T data) {
this.err = err;
this.data = data;
}
public boolean isErr() {
return err;
}
public T getData() {
return data;
}
}
四、Test测试类
public class Test {
public static void main(String[] args) {
BaseDao dao = new BaseDao();
Result<List<List<String>>> result = dao.exeQuery("select * from stusub");
if(!result.isErr()){
List<List<String>> data = result.getData();
for (List<String> row : data) {
for (String col : row) {
System.out.print(col+"\t");
}
System.out.println();
}
}else{
System.out.println("查询异常");
}
}
}