面向接口编程
1. DAO 模式
- DAO 模式就是写一个类,把访问数据库的代码封装起来. DAO 在数据库与业务逻辑(Service)之间.
换句话说, java.sql 包下的内容不能出现在 DAO 层以外. - 实体域, 即操作的对象, 例如我们操作的表是 user 表, 那么就需要写一个 User 类;
- DAO 模式需要先提供 DAO 接口;
- 然后再提供一个 DAO 接口的实现类;
- 再编写一个 DAO 工厂, Service 通过工厂来获取 DAO 实现.
// DAO 层
public class UserDao{
public User findByUsername(String username){
private String path="/Users/姓名/Desktop/users.xml;"
// 查找方法
public User findByUsername(String username){
// 创建解析器
SAXReader reader = new SAXReader();
try{
Document doc = reader.read(path);
// 使用 XPath 查找属性为 username 的元素
Element ele = (Element)doc.selectSingleNode("//user[@username='"+username+"']");
// 如果没有找到, 返回 null
if(ele==null) return null;
// 如果找到了, 返回 User 对象
User user = new User();
String attrUsername = ele.attributeValue("username");
String attrPassword = ele.attributeValue("password");
User.setUsername(attrUsername);
User.setPassword(attrPassword);
return user;
} catch (DocumentException e){
throw new RuntimeException(e);
}
}
// 添加元素方法
public void addUser(User user){
// 创建解析器
SAXReader reader = new SAXReader();
try{
Document doc = reader.read(path);
Element root = doc.getRootElement();
// 添加 user 元素
Element ele = root.addElement("user");
// 添加属性
ele.addAttribute("username",user.getUsername());
ele.addAttribute("password",user.getPassword());
// 回写
OutputFormat format = new OutputFormat("\t",true);
// 清除原有换行和缩进
format.setTrimText(true);
XMLWriter writer = new XMLWriter(
new OutputStreamWriter(
new FileOutputStream(path),"utf-8"),format);
writer.write(doc);
writer.close();
} catch(Exception e){
throw new RuntimeException(e);
}
}
}
}
// service 层
public class UserService{
// 因为依赖 Dao 层, 创建 userDao 对象
private UserDao userDao = new UserDao();
....
}
// 升级版
// 创建 UserDao 接口
pulic interface UserDao{
public void addUser(User form);
public User findByUsername(String username);
}
// 创建 UserDao 接口的实现类
public class UserDaoImpl implements UserDao{
private String path = "/Users/姓名/Desktop/users.xml";
// 查找方法
public User findByUsername(String username){
// 创建解析器对象
SAXReader reader = new SAXReader();
try{
Document doc = reader.read(path);
Element ele = (Element)doc.SelectSingleNode("//user@[username='"+username+"']");
if(ele==null) return null;
String attrUsername = ele.attributeValue("username");
String attrPassword = ele.attributeValue("password");
User user = new User();
user.setUsername(attrUsername);
user.setPassword(attrPassword);
return user;
} catch(DocumentException e){
throw new RuntimeException(e);
}
}
// 添加方法
public void addUser(User user){
SAXReader reader = new SAXReader();
try{
Document doc = reader.read(path);
Element root = doc.getRootElement();
Element ele = root.addElement("user");
ele.addAttribute("username",user.getUsername());
ele.addAttribute("password",user.getPassword());
// 回写 xml
OutputFormat format = new OutputFormat("\t",true);
format.setTrimText(true);
XMLWriter writer = new XMLWriter(
new OutputStreamWriter(
new FileOutpuStream(path),"utf-8"
),format);
writer.write(doc);
writer.close();
} catch(Exception e){
throw new RuntimeException(e);
}
}
}
// src 目录下的 dao.properties
// 其中键为接口名, 值为接口的实现类
cn.itcast.user.dao.UserDao=cn.itcast.user.dao.UserDaoImpl
// 创建 DaoFactory, 提供 getUserDao() 方法
public class DaoFactory{
private static Properties props = null;
static{
// 加载配置文件内容到 props 对象中
try{
InputStream in =
DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
props = new Properties();
props.load(in);
}catch(IOException e){
throw new RuntimeException(e);
}
}
public static UserDao getUserDao(){
// 给出一个配置文件, 文件中给出 UserDao 接口的实现类名称!
// 我们这个方法, 获取实现类的类名, 通过反射完成创建对象!!
// 配置文件 dao.properties 在 src 目录下
/*
* 将配置文件中的内容加载到 props 对象中
* (因为并不需要每回都加载, 所以放到静态代码块中)
* InputStream in =
* DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
*
* Properties props = new Properties();
* props.load(in);
*/
// 得到 dao 实现类的名称
String daoClassName = props.getProperty("cn.itcast.user.dao.UserDao");
// 通过反射来创建实现类的对象
try{
Class clazz = Class.forName(daoClassName);
return (UserDao)clazz.newInstance();
} catch (Exception e){
throw new RuntimeException(e);
}
}
}
// service 层
public class UserService{
// 把具体的实现类的创建, 隐藏到工厂中
private UserDao userDao = DaoFactory.getUserDao();
.....
}
// 创建一个新类, 实现 UserDao 接口, 操作 MySql 数据库
// 使用 MySql 数据库, 需要导包 mysql-connector-java
// 使用 JdbcUtils 小工具类和 dbconfig.properties 来获取 Connection 对象
public class JdbcUserDaoImpl implements UserDao{
public User findByUsername(String username){
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
// 得到 Connection 对象
con = JdbcUtils.getConnection();
// 准备 sql 模板, 创建 PreparedStatement 对象
String sql = "SELECT * FROM user WHERE username=?";
pstmt = con.prepareStatement(sql);
// 为 sql 模板赋值
pstmt.setString(1,username);
// 发送 sql 语句, 返回 ResultSet 对象
rs = pstmt.executeQuery();
if(rs==null) return null;
// 获取 ResultSet 对象中的内容
if(rs.next()){
// 将 ResultSet 对象中的内容封装到 User 对象中
User user = new User();
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}else{
// 如果第一行内容为空,也返回 null.
return null;
}
}catch(Exception e){
throw new RuntimeException(e);
}finally{
try{
if(rs != null) rs.close();
if(pstmt != null) pstmt.close();
if(con != null) con.close();
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
public void addUser(User user){
Connection con = null;
PreparedStatement pstmt = null;
try{
con = JdbcUtils.getConnection();
// 创建 sql 模板, 获取 PreparedStatement 对象
String sql = "INSERT INTO user VALUES(?,?)";
pstmt = con.prepareStatement(sql);
// 为 sql 模板中的参数赋值
pstmt.setString(1,user.getUsername());
pstmt.setString(2,user.getPassword());
// 发送 sql 语句
pstmt.executeUpdate();
} catch(Exception e){
throw new RuntimeException(e);
} finally{
// 关闭资源
try{
if(pstmt != null) pstmt.close();
if(con != null) con.close();
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
}
// 然后只需要修改 dao.properties 配置文件,
// 就可以将数据库 从 xml 文件改为 MySql 数据库
cn.itcast.user.dao.UserDao=cn.itcast.user.dao.JdbcUserDaoImpl
参考资料: