一、信息系统的开发架构
客户层-------显示层-------业务层---------数据层---------数据库
1.客户层:客户层就是客户端,简单的来说就是浏览器。
2.显示层:JSP/Servlet,用于给浏览器显示。
3.业务层:对于数据层的原子操作进行整合。
4.数据层:对于数据库进行的原子操作,增加、删除等;
二、DAO(Data Access Object)介绍
DAO应用在数据层那块,用于访问数据库,对数据库进行操作的类。
三、DAO设计模式的结构
DAO设计模式一般分为几个类:
1.VO(Value Object):一个用于存放网页的一行数据即一条记录的类,比如网页要显示一个用户的信息,则这个类就是用户的类。主要用来做数据库的映射.
2.DatabaseConnection:用于打开和关闭数据库。用于向其他接口提供数据库游标conn.
3.DAO接口:用于声明对于数据库的操作。子类继承后向上转型,覆盖DAO接口的方法.数据操作只需要调用这个接口的方法就行.
4.DAOImpl:必须实现DAO接口,真实实现DAO接口的函数,但是不包括数据库的打开和关闭。
5.DAOProxy:也是实现DAO接口,但是只需要借助DAOImpl即可,但是包括数据库的打开和关闭。
6.DAOFactory:工厂类,含有getInstance()创建一个Proxy类。
四、DAO的好处
DAO的好处就是提供给用户的接口只有DAO的接口,所以如果用户想添加数据,只需要调用create函数即可,不需要数据库的操作。
五、DAO包命名
对于DAO,包的命名和类的命名一定要有层次。
六实例分析:
1.VO层,这个类似于Django的model,做的是将数据库和这个javabean映射起来,每个属性对应的是数据库的一个字段
//采用DAO设计模式,这里是VO类,也就是Value Object类,用户映射数据库 package org.vo; import java.sql.*; public class UserBean{ //映射user表 private int userId; private String username; private String password; private int age; private String sex; public UserBean(String name,String password,int age,String sex){ this.setUsername(name); this.setPassword(password); this.setAge(age); this.setSex(sex); } public void setUserId(int userId) { this.userId = userId; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public void setAge(int age) { this.age = age; } public void setSex(String sex) { this.sex = sex; } public int getUserId() { return (this.userId); } public String getUsername() { return (this.username); } public String getPassword() { return (this.password); } public int getAge() { return (this.age); } public String getSex() { return (this.sex); } }
2.DataBaseConnection层,数据库连接层,操作数据库的链接和关闭,主要用于返回数据库游标和关闭数据库资源
//采用DAO模式,这里做数据库关闭和打开 package org.dbc; import java.sql.*; public class DataBaseConnection{ //游标 private Connection conn = null; //驱动 private static final String DRIVER = "com.mysql.jdbc.Driver"; //用户 private static final String USER = "root"; //链接地址 private static final String URL = "jdbc:mysql://localhost:3306/test"; //密码 private static final String PASS = ""; //构造函数,用于初始化游标 public DataBaseConnection() throws Exception{ Class.forName(this.DRIVER); this.conn = DriverManager.getConnection(this.URL,this.USER,this.PASS); } //得到游标 public Connection getConnection()throws Exception{ return this.conn; } //关闭资源 public void close()throws Exception{ if(this.conn != null){ this.conn.close(); } } }
3.DAO接口层.声明的是javabean的操作接口(供业务逻辑调用的)
//采用DAO模式,这里设置的是DAO接口,用于声明对数据库的操作,但是不实现 package org.dao; import java.util.ArrayList; import org.vo.UserBean; //定义用户Bean的接口 public interface UserBeanImpl{ public boolean createUser(UserBean user)throws Exception; public ArrayList<UserBean> findAll()throws Exception; public UserBean findByName(String name)throws Exception; }
实际上在工厂模式调用的时候是直接调用这个接口的函数,但是直接这样调用是无效的,因为没有实现,所以做法是将一个实现了的接口子类的实例向上转型,然后将接口的方法给覆盖,然后调用.
4.实现DAO接口层
//采用DAO模式,这里必须实现DAO接口,真实实现DAO接口的函数,但是不包括数据库的打开和关闭。 package org.dao.impl; import org.dao.*; import org.vo.*; import java.sql.*; import java.util.*; public class UserBeanDAOImpl implements UserBeanImpl{ //数据库操作的游标 private Connection con; private PreparedStatement stat = null; //构造函数,传入游标(这个类不包含数据库的打开和关闭) public UserBeanDAOImpl(Connection conn){ this.con = conn; } //覆写接口中的方法 public boolean createUser(UserBean user)throws Exception{ String sql = "INSERT INTO `user`(`username`, `password`, `age`, `sex`) VALUES (?,?,?,?)"; this.stat = this.con.prepareStatement(sql); stat.setString(1,user.getUsername()); stat.setString(2,user.getPassword()); stat.setInt(3,user.getAge()); stat.setString(4,user.getSex()); int update = stat.executeUpdate(); if(update>0){ return true; }else{ return false; } } public UserBean findByName(String name)throws Exception{ UserBean u = null; return u; } public ArrayList<UserBean> findAll()throws Exception{ ArrayList<UserBean> users = new ArrayList<UserBean>(); return users; } }
这里通过构造函数传入游标,然后操作数据库,这里没有数据库的连接和释放等操作,这样将连接资源和操作分开,可以很方便的修改数据库配置.
5.Userbean的代理层,相当于在实现DAO接口层定义并实现了用户的操作,但是没对修改和认证权限进行认证,就像代理模式中,首先定义了一个上网方法,直接调用这个方法就能上网,但是还定义了一个供给用户使用的上网方法,在这个方法中先对用户进行验证,并且可以设定用户上网的时间等,然后通过了就调用之前的上网方法,而这里也是有异曲同工的效果.
//这里是用户Bean的代理,也是实现DAO接口,但是只需要借助DAOImpl即可,但是包括数据库的打开和关闭。 package org.dao.impl; import org.dao.*; import java.sql.*; import org.vo.*; import java.util.*; import org.dbc.*; public class UserBeanDAOProxy implements UserBeanImpl{ private DataBaseConnection dbc = null; private UserBeanImpl dao = null; //构造函数,用于初始化私有变量 public UserBeanDAOProxy()throws Exception{ this.dbc = new DataBaseConnection(); this.dao = new UserBeanDAOImpl(dbc.getConnection()); } //覆写接口中的方法 public boolean createUser(UserBean user)throws Exception{ boolean flag = false; //如果用户不存在,就创建一个新的用户 if(dao.findByName(user.getUsername()) == null){ flag = this.dao.createUser(user); } //调用数据库层的close方法(在数据库层实际上是执行了游标的关闭) this.dbc.close(); //返回标志 return flag; } public UserBean findByName(String name)throws Exception{ UserBean u = null; return u; } public ArrayList<UserBean> findAll()throws Exception{ ArrayList<UserBean> users = new ArrayList<UserBean>(); return users; } }
可以看到,这里实际上对实现DAO接口类的原子操作进行了整合,比如创建用户的话,那么首先判断用户是否存在等,而这个也是用来专门覆写接口的.
6.DAOFactory类,是一个工厂类.主要是将业务进行分层,用户只需要通过factory调用相应的方法就行,而屏蔽了上面所有的细节.
//采用DAO设计模式,含有一个UserBean接口的实例 package org.dao.factory; import org.dao.*; import java.sql.*; import org.vo.*; import java.util.*; import org.dbc.*; import org.dao.impl.*; public class UserBeanFactory{ public static UserBeanImpl getInstance(){ UserBeanImpl instance = null; try{ instance = new UserBeanDAOProxy(); }catch(Exception e){ e.printStackTrace(); } return instance; } }
可以看到,这里实际上是定义了一个用户bean操作接口,然后通过传入用户bean操作代理,发生向上转型,方法被覆写,然后调用接口的方法就可以实现对应的操作.
我们现在来分析下框架,这样做有很好的扩展性:
1.比如要对存储方法进行改变,如果是更改数据库的话只需要更改DataBaseConnection类中的配置即可,其他部分只关心得到的游标,不关心数据库的链接等问题.
2.现在该更改存储方式,比如改成用文件存储,那么用户操作接口是不用改变的,只需要重新写一个文件的存储方法继承用户bean操作接口并且实现.然后DAO代理的构造函数中传入新的存储方法即可