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来防止样板化代码。