封装数据访问对象
成都创新互联是专业的郓城网站建设公司,郓城接单;提供成都网站设计、网站建设、外贸网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行郓城网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!
1:通过分析总结,所有对数据库表的操作都可以总结为通过JDBC对表的增删改查,为了减少冗余代码,
使得每次操作表时,不必都写JDBC程序,所以将对一张表的所有数据访功能,封装在数据访问对象
(Data Access Object)中,方便调用。
2:为了方便数据传输,往往会将java程序中所有相关操作的零散字段值,封装成一个实体对象--entity。
实体封装原则:
表----实体类
字段---属性
实现序列化
提供set,get方法。
以下代码就是利用Dao数据访问对象写出的JDBC程序,利用封装简化了JDBC开发步骤。
试想一下,如果,有10个添加,20个删除的请求,还像JDBC1.0,2.0版本那样写的话,要写10遍,20遍大量相似代码,
基本一致的代码。这不仅耗时耗力,也不符合JAVA三大特性。所以,利用Dao数据访问层,将对表的常用操作,
封装成方法,这样再有10个添加或20个删除,我们只需要调用10次,20次这个封装好的添加或删除方法,
而不用再写那么多遍方法,大大简化了开发工作量。
以下是利用Dao思想实现的JDBC3.0是3.0版本后面还有更好的版本娓娓道来!>_<
JDBC_Dao.java
public class JDBC_Dao {
/**
* 向account表增加一条记录
*/
public void add(Account account){
Connection conn = null;
PreparedStatement pstm = null;
try {
//1加载驱动
Class.forName("com.MySQL.jdbc.Driver");
//2创建连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
//3准备sql
String sql = "insert into account values(?,?,?,?)";
//4创建Statement,发送sql
pstm = conn.prepareStatement(sql);
pstm.setString(1,account.getCardId());
pstm.setString(2, account.getPassword());
pstm.setDouble(3, account.getBalance());
pstm.setString(4, account.getPhone());
int i = pstm.executeUpdate();
//5如果是查询的话,处理结果集
} catch (Exception e) {
e.printStackTrace();
}
finally{
//6释放资源
try {
pstm.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 向account表查询一条记录
* @param account
* @return
*/
public Account query(Account account){
Connection conn = null;
PreparedStatement pstm =null;
ResultSet rs = null;
try {
//1加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2创建连接
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
//3准备sql
String sql = "select * from account where "
+ "card_id = ? and password = ?";
//4创建Statement发送语句
pstm = conn.prepareStatement(sql);
pstm.setString(1, account.getCardId());
pstm.setString(2, account.getPassword());
rs = pstm.executeQuery();
//5处理结果集
while (rs.next()) {
account.setCardId(rs.getString("card_id"));
account.setPassword(rs.getString("password"));
account.setBalance(rs.getDouble("balance"));
account.setPhone(rs.getString("phone"));
}
} catch (Exception e) {
e.getStackTrace();
}
finally{
//6释放资源
try {
rs.close();
pstm.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return account;
}
}
以上代码依旧使用account表,需要再写一个实体对象用来承载数据,一个test类用来调用方法,
,这些最基础的,这里就不赘述了,不清楚的同学就要自行参阅java语言了。
如果我查询A卡,B卡,C卡,三张银行卡信息,按照JDBC2.0要写三个查询方法,现在,只需要把参数传递过去,
调用三次query()方法就好了!
总结:可见利用Dao数据访问层封装JDBC常用方法,可以大大简化方法步骤,不用重复写方法,只需重复调用。
这就是JDBC3.0版本
=============================华丽丽的分割线================
但是仔细的读者一定发现了,这里还存在不少缺陷,没错,我们还可以改进它。
在JDBC3.0版本里,可以发现,查询,添加方法,存在大量冗余代码,比如:
①同的加载驱动, ②相同的创建连接,③相同的释放资源。
在上个版本的代码里我只写了添加查询方法,如果还有删除,修改,查询所有等方法呢,
没错这些方法,也存在相同的创建连接,释放链接。找见了问题,就好解决了。
那么解决的办法还是----封装。
我们可以尝试把1注册驱动,2创建连接,6释放资源,这三个步骤做成工具类-----JDBCutil
这样,我们在Dao层里面的JDBC方法,在遇到1,2,6等步骤时,不用再去写代码,只需调用封装好的工具即可。
没错程序员都是很懒得!
以下是JDBC4.0是4.0版本,后面还有更完善的版本娓娓道来!
public class JDBC_Util {
/**
* @return 返回链接
*/
public static Connection getConnection() throws Exception {
Connection conn = null;
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
return conn;
}
/**
* 释放资源
*/
public static void release(ResultSet rs,
Statement stm,
Connection conn){
try {
if(rs!=null){rs.close();}
if(stm!=null){stm.close();}
if(conn!=null){conn.close();}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class JDBC_Dao2 {
/**
* 向account表增加一条记录
*/
public void add(Account account){
Connection conn = null;
PreparedStatement pstm = null;
try {
conn = JDBC_Util.getConnection();
//3准备sql
String sql = "insert into account values(?,?,?,?)";
//4创建Statement,发送sql
pstm = conn.prepareStatement(sql);
pstm.setString(1,account.getCardId());
pstm.setString(2, account.getPassword());
pstm.setDouble(3, account.getBalance());
pstm.setString(4, account.getPhone());
int i = pstm.executeUpdate();
//5如果是查询的话,处理结果集
} catch (Exception e) {
e.printStackTrace();
}
finally{
//6释放资源
JDBC_Util.release(null, pstm, conn);
}
}
/**
* 向account表查询一条记录
* @param account
* @return
*/
public Account query(Account account){
Connection conn = null;
PreparedStatement pstm =null;
ResultSet rs = null;
try {
conn = JDBC_Util.getConnection();
//3准备sql
String sql = "select * from account where " + "card_id = ? and password = ?";
//4创建Statement发送语句
pstm = conn.prepareStatement(sql);
pstm.setString(1, account.getCardId());
pstm.setString(2, account.getPassword());
rs = pstm.executeQuery();
//5处理结果集
while (rs.next()) {
account.setCardId(rs.getString("card_id"));
account.setPassword(rs.getString("password"));
account.setBalance(rs.getDouble("balance"));
account.setPhone(rs.getString("phone"));
}
} catch (Exception e) {
e.getStackTrace();
}
finally{
//6释放资源
JDBC_Util.release(rs, pstm, conn);
}
return account;
}
}
细心地读者会发现在代码里原本创建连接和释放资源的位置都变成了方法调用。
conn = JDBC_Util.getConnection();
JDBC_Util.release(rs, pstm, conn);
4.0版本通过工具类调用的方式进一步精简了代码,那么4.0版本还有没有缺陷了呢。
=======================华丽丽的分割线============================
对于JDBC_Util.java来说,还有许多不足。
1:
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/zdx?serverTimezone=UTC",
"root",
"root");
比如创建连接的方式,是在代码里写死的用户名和密码,以及连接url,而java文件运行的时候,会编译成class文件
也就是说,JDBC_Util最终会是JDBC_Util.class文件,那么一旦数据库改变密码,用户名,或改换数据库,
整个文件还需要重新编译执行。对此,我们可以把经常变动的代码放到properties配置文件里去。
2:每次调用获得连接的方法都需要加载驱动,
Class.forName("com.mysql.jdbc.Driver");
调用10次则加载10次,大大浪费了JVM内存,其实对于加载驱动只需要加载一次,我们可以尝试把加载驱动放到
静态代码块里。静态代码块在类加载时执行,只执行一次。
properties配置文件简介及使用:
1: InputStream is = new FileInputStream("配置文件路径");
BufferedReader br = bew BufferedReader(new InputStramReader(is));
String as = br.readLine();
2:properties 是Map的实现类:
1:获得配置文件的输出流。
2:调用load(is);加载配置文件里的信息至Properties对象中。
下面的JDBC5.0版本是对JDBC_Util的改进。采用了静态代码块加读取配置文件的优化方案。
包括test.java,JDBC_Util2.java,JDBC_Dao2.java,properties文件,共四个。
JDBC_Uril2.java
public class JDBC_Util2 {
private static final Properties prop = new Properties();
static{
InputStream is = null;
try {
is = JDBC_Util2.class.getResourceAsStream("jdbc.properties");
prop.load(is);
String driverName = prop.getProperty("driverName");
Class.forName(driverName);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @return 返回链接
*/
public static Connection getConnection() throws Exception {
Connection conn = null;
String user = prop.getProperty("user");
String password = prop.getProperty("password");
String url = prop.getProperty("url");
conn = DriverManager.getConnection(url,user,password);
return conn;
}
/**
* 释放资源
*/
public static void release(ResultSet rs,
Statement stm,
Connection conn){
try {