Data Access Object(DAO)
DAO设计模式
DAO(数据库操作对象)设计模式是JavaEE数据层的操作。
DAO抽象与封装所有对数据源的访问;负责管理对数据源的连接,以及数据的存取。
DAO包括五个重要的部分,分别如下:
(1)数据库连接类
(2)VO类
(3)DAO接口
(4)DAO实现类
(5)DAO工厂类
1.数据库连接类
数据库连接类的主要功能是连接数据库并获得连接对象,以及关闭数据库。通过数据库连接类可以大大的简便开发,在需要进行数据库连接时,只需创建该类的实例,并调用其中的方法就可以获得数据库连接对象和关闭数据库,不必再进行重复操作。
package com.inquiry.mis.worknotes.common;
import java.sql.*;
import java.util.Properties;
/**
* 该类用户建立数据库的连接,和操作
*/
public class Dbconnector
{
//指定需要访问的数据库名称
private static final String url="jdbc:mysql://localhost:3306/worknotes";
//指定需要访问的数据库的驱动程序的名称
private static final String driver="com.mysql.jdbc.Driver";
//数据库连接的用户名和密码
private static final String user="dev";
private static final String passwd="dev";
/**
* 用于连接数据库
*/
private Connection connection;
/**
* 用于执行数据库SQL语句
*/
private Statement statement;
/**
*用于存放SQL语句的执行结果
*/
private ResultSet rs;
/**
* 创建一个到指定数据库的连接
*/
public Dbconnector()
{
Properties props = new Properties();
props.put("user",user);
props.put("password", passwd);
try{
//返回该字串对应的类对象
Class.forName(driver);
//建立数据库的连接
connection=DriverManager.getConnection(url,props);
//创建SQL语句的载体
statement=connection.createStatement();
}
catch (ClassNotFoundException ex)
{ //获取类对象失败
ex.printStackTrace();
throw new DAORuntimeException("ClassNotFoundException:Cannot find the database driver classes.");
}
catch (SQLException ex)
{ //SQL语句构造错误
ex.printStackTrace();
throw new DAORuntimeException("SQLException:Cannot connect to database.");
}
}
/**
* 获取数据库的连接
* @return 返回对指定数据库的连接
*/
public Connection getConnection(){
return connection;
}
/**
* 获取数据库的SQL控制权
* @return 返回对指定数据库的控制权
*/
public Statement getStatement(){
return statement;
}
/**
* 用于执行SQL操作
* @param query 待执行的SQL语句
*/
public void executeUpdate(String query)
{
if (connection==null || statement==null)
{
throw new DAORuntimeException("There is no database to execute the query.");
}
try{
statement.executeUpdate(query);
}catch (SQLException ex) {
ex.printStackTrace();
throw new DAORuntimeException("SQLException: Cannot execute SQL");
}
}
/**
* 执行SQL查询
* @param query 待执行的SQL语句
* @return 查询结果
*/
public ResultSet executeQuery(String query)
{
if (connection==null || statement==null)
{
throw new DAORuntimeException("There is no database to execute the query.");
}
try{
rs=statement.executeQuery(query);
} catch (SQLException ex) {
ex.printStackTrace();
throw new DAORuntimeException("SQLException: Cannot execute SQL");
}
return rs;
}
/**
* 关闭指定的数据库连接
*/
public void close()
{
try{
rs.close();
statement.close();
connection.close();
}catch(SQLException ex){
ex.printStackTrace();
throw new DAORuntimeException("SQLException:cannot close database !");
}
}
/**
* 通过销毁对象方式 关闭数据库
*/
public void finallize()
{
try{
rs.close();
statement.close();
connection.close();
super.finalize();
}catch(Throwable ex){
ex.printStackTrace();
throw new DAORuntimeException("Fatal Error!");
}
}
}
2.VO类(POJO)
VO类是一个包含属性和表中字段完全对应的类。并在该类中提供set和get方法来设置并获得该类中的属性。
一个vo类与一个数据库中的表相对应,也就是说,有多少表,就应该有多少vo类。而实例化的vo对象则代表一个表中的一行数据。
package com.inquiry.mis.worknotes.domain;
import java.sql.Timestamp;
import java.io.Serializable;
/**
* 日志录入账户
*/
public class Account implements Serializable {
public String getPk_userid() {
return pk_userid;
}
public void setPk_userid(String pk_userid) {
this.pk_userid = pk_userid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Timestamp getCreatetime() {
return createtime;
}
public void setCreatetime(Timestamp createtime) {
this.createtime = createtime;
}
public Timestamp getUpdatetime() {
return updatetime;
}
public void setUpdatetime(Timestamp updatetime) {
this.updatetime = updatetime;
}
public int getFk_personID() {
return fk_personID;
}
public void setFk_personID(int fk_personID) {
this.fk_personID = fk_personID;
}
public String getWill1() {
return will1;
}
public void setWill1(String will1) {
this.will1 = will1;
}
public String getWill2() {
return will2;
}
public void setWill2(String will2) {
this.will2 = will2;
}
public short getWorkstatus() {
return workstatus;
}
public void setWorkstatus(short workstatus) {
this.workstatus = workstatus;
}
private String pk_userid;
private String password;
private short workstatus;
private Timestamp createtime;
private Timestamp updatetime;
private int fk_personID;
private String will1;
private String will2;
}
3.DAO接口
DAO接口中定义了所有的用户的操作,如添加记录、删除记录以及查询记录等。不过因为是接口,所以仅仅是定义,需要子类来实现。
package com.inquiry.mis.worknotes.dao;
import com.inquiry.mis.worknotes.domain.Account;
import java.util.List;
/**
* 日志录入账户的DAO
*/
public interface AccountDao {
/**
* 将account对象的数据保存到数据库中
* @param account 传入的Account 对象(VO)
*/
public void creat(Account account);
/**
* 根据当前的Account对象,在数据库中创建持久数据。
* @param account 指定的Accont对象
*/
public void update(Account account);
/**
* 根据指定的记录id,从数据库中删除指定的Account数据。
* @param id 待删除的Account记录ID
*/
public void delete(int id);
/**
* 根据指定的记录id,从数据库中取得详细信息。
* @param id 待查询的Account记录ID
* @return 指定的Account对象
*/
public Account getDetail(int id);
/**
* 根据提供的用户名和密码,从数据库中取得详细信息。
* @param userid 待查询的系统账户ID
* @param passwd 待查询的账户密码
* @return 如果找到符合的记录就返回相应的Account对象,否则返回null
*/
public Account getDetailbyUSR$PWD(String userid,String passwd);
/**
* 从数据库中取得 所有的Account数据。
* @return 返回取得的Account 对象的队列。
*/
public List getList();
}
4.DAO实现类
DAO实现类实现了DAO接口,并实现了DAO接口中定义的所有方法。在DAO实现中通过连接数据库进行数据库操作。
一个Dao实现类对应一个表,如AccountDao类对应Account表,该类中将定义对该表的所有的操作。
package com.inquiry.mis.worknotes.dao.jdbc;
import com.inquiry.mis.worknotes.dao.AccountDao;
import com.inquiry.mis.worknotes.domain.Account;
import com.inquiry.mis.worknotes.common.Primary;
import com.inquiry.mis.worknotes.common.Dbconnector;
import com.inquiry.mis.worknotes.common.DAORuntimeException;
import java.util.List;
import java.util.Vector;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.io.UnsupportedEncodingException;
public class AccountDaoImpl implements AccountDao {
//创建SQL常量
final static String TABLE_NAME="account_main";
final static String SQL_GET_BY_UID$PWD="SELECT * FROM "+TABLE_NAME+" WHERE PK_UserID=? AND password=? AND STATUS="+Primary.ENABLE;
final static String SQL_GET_ALL="SELECT * FROM "+TABLE_NAME+" WHERE STATUS= "+Primary.ENABLE;
//预处理对象定义
private PreparedStatement m_accountGetByUID$PWD=null;
public void creat(Account account) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void update(Account account) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void delete(int id) {
//To change body of implemented methods use File | Settings | File Templates.
}
public Account getDetail(int id) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public Account getDetailbyUSR$PWD(String userid, String passwd) {
Account account=null;
//获得数据库连接
Dbconnector dbconnector=new Dbconnector();
try{
//查询数据初始化
m_accountGetByUID$PWD=dbconnector.getConnection().prepareStatement(SQL_GET_BY_UID$PWD);
//准备查询用的CodeType,CodeID
m_accountGetByUID$PWD.setString(1,userid);
m_accountGetByUID$PWD.setString(2,passwd);
//获取查询结果
ResultSet rs=m_accountGetByUID$PWD.executeQuery();
if (rs==null) return null;
else if (rs.next()==false) return null;
account = new Account();
//将数据装入到VO--account的对象中去
account.setPk_userid(userid);
account.setPassword(passwd);
account.setFk_personID(rs.getInt(3));
account.setWorkstatus(rs.getShort(4));
account.setCreatetime(rs.getTimestamp(6));
account.setUpdatetime(rs.getTimestamp(7));
account.setWill1(rs.getString(8));
account.setWill2(rs.getString(9));
}catch (SQLException ex){
ex.printStackTrace();
throw new DAORuntimeException("set prepare error "+ex.getMessage());
}
return account;
}
public List getList() {
List lst = new Vector();
//获得数据库连接
Dbconnector dbconnector=new Dbconnector();
//执行数据库查询操作
ResultSet rs = dbconnector.executeQuery(SQL_GET_ALL);
if(rs==null){
return lst;
}else{
try {
while(rs.next()){
//将数据装入到一个新的 VO--CodeRef的对象中去
Account account=new Account();
account.setPk_userid(rs.getString(1));
account.setPassword(rs.getString(2));
account.setFk_personID(rs.getInt(3));
account.setWorkstatus(rs.getShort(4));
account.setCreatetime(rs.getTimestamp(6));
account.setUpdatetime(rs.getTimestamp(7));
account.setWill1(rs.getString(8));
account.setWill2(rs.getString(9));
lst.add(account); //将最新查询的对象放入队列中
}
} catch (SQLException ex) {
ex.printStackTrace();
throw new DAORuntimeException("sql error "+ex.getMessage());
}
}
return lst; //返回查询的CodeRef 数据对象的 队列
}
}
5.DAO工厂类
在没有DAO工厂类的情况下,必须通过创建DAO实现类的实例才能完成数据库操作,对于后期的修改非常不便。有时要修改所有的使用DAO实现类的代码。
使用DAO工厂类可以很好的解决后期修改的问题,可以通过该DAO工厂类的一个静态方法来获得DAO实现类实例。这时如果需要替换DAO实现类,只需修改该DAO工厂类中的方法代码,而不必修改所有的操作数据库代码。用flag来选择执行那种数据库访问方法
package com.inquiry.mis.worknotes.dao;
import com.inquiry.mis.worknotes.dao.jdbc.*;
import com.inquiry.mis.worknotes.dao.ibatis.DaoConfig;
/**
* DAO对象静态工厂类.
*
*/
public class DaoFactory {
static int flag=1;
public static AccountDao createAccountDao(){
if (flag==1)
return new AccountDaoImpl();
if (flag==2)
return (AccountDao) DaoConfig.getDaoManager().getDao(AccountDao.class);
return null;
}
public static CodeRefDao createCodeRefDao(){
if (flag==1)
return new CodeRefDaoImpl();
if (flag==2)
return (CodeRefDao) DaoConfig.getDaoManager().getDao(CodeRefDao.class);
return null;
}
}