DAO(Data Access Object, 数据拜访对象),次要的性能是用于进行数据操作的,在程序的规范开发框架中属于数据层的操作。
数据开发构造:
资源层是数据库的操作层,外面能够进行各种数据库的存储,然而这些数据存储的时候必定是依附 SQL 语句,数据层通过一个专门的数据库组件实现对数据库的操作
业务层是整个我的项目的外围
DAO 组成
DatabaseConnection:专门负责数据库关上与敞开操作的类
VO:次要由属性,setter, getter 办法组成,VO 类中的属性与表中的字段绝对应,每一个 VO 类的对象都示意表中的每一条记录;
DAO:次要定义操作的接口,定义一系列数据库的原子性操作,例如增删改查等;
Impl: DAO 接口的实在实现类,次要实现具体数据库操作,但不负责数据库的关上和敞开;
Proxy:代理实现类,次要实现数据库的关上和敞开并且调用实在实现类对象的操作;
Factory: 工厂类,通过工厂类获得一个 DAO 的实例化对象。
对于包的命名:
在应用 DAO 时对包有严格的命名
- 数据库连贯:xxx.dbc.DatabaseConnection
- DAO 接口:xxx.dao.IXxxDAO
- DAO 接口实在实现类:xxx.dao.impl.XxxDAOImpl
- DAO 接口代理实现类:xxx.dao.proxy.XxxDAOProxy
- VO 类:xxx.vo.Xxx, VO 命名要与表的命名统一
- 工厂类:xxx.factory.DAOFactory.
-
施行 DAO 模式 (Implementing DAO pattern)**
应用上述组件,让咱们尝试实现 DAO 模式。咱们将在这里应用 3 个组件:
1. 从一层转移到另一层的 book 模型。
2.bookdao 接口提供了灵便的设计和要实现的 API。
3.BookDaoImpl 具体类,它是 bookdao 接口的实现
DAO 模式的劣势 **
应用 DAO 模式有很多长处。让咱们在这里申明其中一些:
在更改持久性机制时,服务层甚至不用晓得数据来自何处。例如,如果您正在思考从应用 MySQL 过渡到 MongoDB,则所有更改仅须要在 DAO 层中实现。
DAO 模式强调应用程序不同组件之间的低耦合。因而,View 层不依赖于 DAO 层,而仅 Service 层依赖于 DAO 层,即便依赖于接口,也不依赖于具体的实现。
因为持久性逻辑是齐全独立的,因而为单个组件编写单元测试要容易得多。例如,如果将 JUnit 和 Mockito 用于测试框架,则能够轻松模仿应用程序的各个组件。
当咱们以 DAO 模式应用接口时,它还强调了“应用接口代替实现”的格调,这是一种杰出的 OOPs 编程格调。
什么状况下产生模式
当咱们的业务和数据都要解决的时候,然而业务和数据都是不同的实现形式,然而它们之间又有分割,所以这里就产生理解耦概念。独自封装一个类来解决数据的代码
当解决业务和数据的代码在一起的时候,会呈现以下状况:
1. 保护艰难因为每该一次数据都会影响业务代码。
2. 代码复用比拟低
3. 编写业务层代码的人员必须要懂各种数据保留形式
MyBatis 开发 Dao 模式过程 **
Mybatis 框架依据接口定义创立接口的动静代理对象,代理对象的办法体同上边 Dao 接口实现类办法。
应用 mapper 代理的办法来开发 dao 时,程序员只须要干两件事即可:
1、编写 mapper.xml 映射文件 2、编写 mapper 接口(相当于 dao 接口)
Mapper 接口开发须要遵循以下四个标准 (倡议初学者联合下图了解):1、Mapper.xml 文件中的 namespace 与 mapper 接口的类门路雷同。2、Mapper 接口办法名和 Mapper.xml 中定义的每个 statement 的 id 雷同 3、Mapper 接口办法的输出参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型雷同 4、Mapper 接口办法的输入参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型雷同
Mapper 接口开发四个标准属实有点吃力,我就在掘金上废了点劲找到了图,不便了解:**
-
原始 Dao 开发方式 **
原始 Dao 开发方法须要程序员编写 Dao 接口和 Dao 实现类。
1. 编写映射文件 **
编写映射文件如下:(也能够应用入门程序实现的映射文件)
<?xml version=”1.0″ encoding=”UTF-8″ ?>
<!DOCTYPE mapper
PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-mapper.dtd”>
<!– namespace:命名空间,用于隔离 sql,还有一个很重要的作用,前面会讲 –>
<mapper namespace=”test”>
<!– 依据 id 查问用户 –>
<select id=”queryUserById” parameterType=”int”
resultType=”com.gx.mybatis.pojo.User”>
select * from user where id = #{id}
</select>
<!– 依据 username 含糊查问用户 –>
<select id=”queryUserByUsername” parameterType=”string”
resultType=”com.gx.mybatis.pojo.User”>
select * from user where username like ‘%${value}%’
</select>
<!– 保留用户 –>
<insert id=”saveUser” parameterType=”com.gx.mybatis.pojo.User”>
<selectKey keyProperty=”id” keyColumn=”id” order=”AFTER”
resultType=”int”>
SELECT 1576193
</selectKey>
insert into user(username,birthday,sex,address)
values(#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
2. 编写 Dao 接口 **
先进行 DAO 的接口开发,编码如下:
public interface UserDao {
/**
- 依据 id 查问用户
*
- @param id
- @return
*/
User queryUserById(int id);
/**
- 依据用户名含糊查问用户
*
- @param username
- @return
*/
List<User> queryUserByUsername(String username);
/**
- 保留用户
*
- @param user
*/
void saveUser(User user);
}
3. 编写 Dao 实现类 **
编写的 Dao 实现类如下
public class UserDaoImpl implements UserDao {
private SqlSessionFactory sqlSessionFactory;
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
super();
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User queryUserById(int id) {
// 创立 SqlSession
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 执行查问逻辑
User user = sqlSession.selectOne(“queryUserById”, id);
// 开释资源
sqlSession.close();
return user;
}
@Override
public List<User> queryUserByUsername(String username) {
// 创立 SqlSession
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 执行查问逻辑
List<User> list = sqlSession.selectList(“queryUserByUsername”, username);
// 开释资源
sqlSession.close();
return list;
}
@Override
public void saveUser(User user) {
// 创立 SqlSession
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 执行保留逻辑
sqlSession.insert(“saveUser”, user);
// 提交事务
sqlSession.commit();
// 开释资源
sqlSession.close();
}
}
4. 编写 Dao 测试 **
创立一个 JUnit 的测试类,对 UserDao 进行测试(充当 main 办法),测试代码如下:
public class UserDaoTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws Exception {
// 创立 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 加载 SqlMapConfig.xml 配置文件
InputStream inputStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
// 创立 SqlsessionFactory
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
}
@Test
public void testQueryUserById() {
// 创立 DAO
UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
// 执行查问
User user = userDao.queryUserById(1);
System.out.println(user);
}
@Test
public void testQueryUserByUsername() {
// 创立 DAO
UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
// 执行查问
List<User> list = userDao.queryUserByUsername(“ 五 ”);
for (User user : list) {
System.out.println(user);
}
}
@Test
public void testSaveUser() {
// 创立 DAO
UserDao userDao = new UserDaoImpl(this.sqlSessionFactory);
// 创立保留对象
User user = new User();
user.setUsername(“ 孙尚香肠 ”);
user.setBirthday(new Date());
user.setSex(“1”);
user.setAddress(“ 蜀国 ”);
// 执行保留
userDao.saveUser(user);
System.out.println(user);
}
}
Mapper 动静代理形式 **
1. 定义 Mapper.xml(映射文件)**
定义 mapper 映射文件 UserMapper.xml 将 UserMapper.xml 放在 config 下 mapper 目录下,成果如下:
2、编写 UserMapper.xml 配置文件内容:**
<?xml version=”1.0″ encoding=”UTF-8″ ?>
<!DOCTYPE mapper
PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-mapper.dtd”>
<!– namespace:命名空间,用于隔离 sql –>
<!– 还有一个很重要的作用,应用动静代理开发 DAO,1. namespace 必须和 Mapper 接口类门路统一 –>
<mapper namespace=”com.gx.mybatis.mapper.UserMapper”>
<!– 依据用户 id 查问用户 –>
<!– 2. id 必须和 Mapper 接口办法名统一 –>
<!– 3. parameterType 必须和接口办法参数类型统一 –>
<!– 4. resultType 必须和接口办法返回值类型统一 –>
<select id=”queryUserById” parameterType=”int”
resultType=”com.gx.mybatis.pojo.User”>
select * from user where id = #{id}
</select>
<!– 依据用户名查问用户 –>
<select id=”queryUserByUsername” parameterType=”string”
resultType=”com.gx.mybatis.pojo.User”>
select * from user where username like ‘%${value}%’
</select>
<!– 保留用户 –>
<insert id=”saveUser” parameterType=”com.gx.mybatis.pojo.User”>
<selectKey keyProperty=”id” keyColumn=”id” order=”AFTER”
resultType=”int”>
select 1576193
</selectKey>
insert into user(username,birthday,sex,address) values
(#{username},#{birthday},#{sex},#{address});
</insert>
</mapper>
3. 编写 UserMapper(接口文件)**
创立 UserMapper 接口代码如下:
public interface UserMapper {
/**
- 依据 id 查问
*
- @param id
- @return
*/
User queryUserById(int id);
/**
- 依据用户名查问用户
*
- @param username
- @return
*/
List<User> queryUserByUsername(String username);
/**
- 保留用户
*
- @param user
*/
void saveUser(User user);
}
4. 加载 UserMapper.xml 文件 **
批改 SqlMapConfig.xml 文件,增加以下所示的内容:
<!– 加载映射文件 –>
<mappers>
<mapper resource=”sqlmap/User.xml” />
<mapper resource=”mapper/UserMapper.xml” />
</mappers>
5. 编写测试 **
编写的测试方法如下:
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws Exception {
// 创立 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 加载 SqlMapConfig.xml 配置文件
InputStream inputStream = Resources.getResourceAsStream(“SqlMapConfig.xml”);
// 创立 SqlsessionFactory
this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
}
@Test
public void testQueryUserById() {
// 获取 sqlSession,和 spring 整合后由 spring 治理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 从 sqlSession 中获取 Mapper 接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法
User user = userMapper.queryUserById(1);
System.out.println(user);
// 和 spring 整合后由 spring 治理
sqlSession.close();
}
@Test
public void testQueryUserByUsername() {
// 获取 sqlSession,和 spring 整合后由 spring 治理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 从 sqlSession 中获取 Mapper 接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法
List<User> list = userMapper.queryUserByUsername(“ 五 ”);
for (User user : list) {
System.out.println(user);
}
// 和 spring 整合后由 spring 治理
sqlSession.close();
}
@Test
public void testSaveUser() {
// 获取 sqlSession,和 spring 整合后由 spring 治理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 从 sqlSession 中获取 Mapper 接口的代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 创立保留对象
User user = new User();
user.setUsername(“ 刘备胎 ”);
user.setBirthday(new Date());
user.setSex(“2”);
user.setAddress(“ 鼠国 ”);
// 执行查询方法
userMapper.saveUser(user);
System.out.println(user);
// 和 spring 整合后由 spring 治理
sqlSession.commit();
sqlSession.close();
}
}
总结 **
长处 **
应用数据拜访对象的长处是应用程序的两个重要局部之间绝对简略并严格拆散,它们能够但不应该彼此理解任何货色,并且两者可预期的频繁和独立倒退。扭转业务逻辑能够依赖于雷同的 DAO 接口,而对持久性逻辑的更改只有接口放弃正确实现,就不会影响 DAO 客户端。存储的所有细节都暗藏在应用程序的其余部分中(见信息暗藏)。因而,能够批改一个 DAO 实现而不影响应用程序的其余部分,从而可能实现对持久性机制的更改。DAO 充当了应用程序与数据库之间的中介,它们在对象与数据库记录之间来回转移数据。用测试替身取代 DAO 能够促成代码的单元测试,使测试不依赖于长久层。
在 Java 编程语言的非特定上下文中,数据拜访对象作为一项设计概念能够用多种形式实现。这能够将应用程序中的数据拜访局部拆散为非常简单的接口,迁徙到框架或商业产品。DAO 编码范例可能须要一些技巧。像是 Java Persistence API 和 Enterprise JavaBeans 之类的技术已内置在应用程序服务器中,能够在 JavaEE 应用程序服务器的应用程序中应用。商业产品如 TopLink 能够在基于对象关系映射(ORM)的产品上应用。风行的开源 ORM 产品包含 Doctrine (PHP))、Hibernate、iBATIS,以及 JPA 实现(例如 Apache OpenJPA)。
毛病 **
应用 DAO 的潜在毛病包含形象透露、代码反复和形象反演。尤其是将 DAO 作为惯例 Java 对象的形象会暗藏每个数据库拜访的高老本,并且可能强制开发人员触发多个数据库查问来检索一般 SQL 查问中一次就可取回的信息。如果一个应用程序须要多个 DAO,人们可能发现自己对每个 DAO 反复基本上雷同的创立、读取、更新和删除代码。不过,也能够实现一个解决罕用操作的通用 DAO 来防止样板化代码。