MyBatis开发DAO的方式
MyBatis开发Dao有两种方式:原始Dao的开发方式,Mapper动态代理的方式。
两种开发方式在企业开发中均有运用。都要掌握。
使用myBatis时,需要对其进行一个全局的管理配置。
sqlMappingConfig.xml
[html] view plain copy
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
- <!-- 加载属性文件-->
- <properties resource="db.properties"></properties>
- <!-- 全局参数配置,在需要时候进行配置 -->
- <!-- <settings></settings> -->
- <!-- 别名设置 -->
- <!-- 单个配置
- type:类型路径
- alias:别名-->
- <!-- <typeAliases>
- <typeAlias type="cn.edu.hpu.ssm.po.User" alias="user"/>
- </typeAliases> -->
- <!-- 批量设置(推荐使用)
- 指定包名,mybatis自动扫描扫描po类,自动定义别名。默认为类名(首字母大写或小写) -->
- <typeAliases>
- <package name="cn.edu.hpu.ssm.po"/>
- </typeAliases>
- <!-- 和spring整合后 environments配置将废除-->
- <environments default="development">
- <environment id="development">
- <!-- 使用jdbc事务管理,事物控制有mybatis控制-->
- <transactionManager type="JDBC" />
- <!-- 数据库连接池,由mybatis管理-->
- <dataSource type="POOLED">
- <property name="driver" value="${jdbc.driver}" />
- <property name="url" value="${jdbc.url}" />
- <property name="username" value="${jdbc.username}" />
- <property name="password" value="${jdbc.password}" />
- </dataSource>
- </environment>
- </environments>
- <!-- 配置mpper,加载映射文件 -->
- <!-- <mappers>
- <mapper resource="sqlmap/User.xml"/>
- <mapper resource="mapper/UserMapper.xml"/>
- </mappers> -->
- <!-- 通过mapper接口,加载映射文件
- 规范:mapper接口名必须与mapper。xml文件名相同,且放在同一包下
- 前提是使用mapper代理的方式 -->
- <mappers>
- <mapper class="cn.edu.hpu.ssm.mapper.UserMapper"/>
- <mapper class="cn.edu.hpu.ssm.mapper.OrdersMapperCustom"/>
- </mappers>
- </configuration>
其中关于数据库的一些配置,抽取出来了,这样可以减少硬编码:
db.properties:
[plain] view plain copy
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/mybatis
- jdbc.username=root
- jdbc.password=123456
1.原始Dao的开发方式
原始Dao的开发,需要程序员自己编写Dao的接口和Dao接口的实现类。(一下以一个按照id查询为例说明)
1.映射文件:
[html] view plain copy
- <?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进行分类化管理,sql隔离
- 注意:在使用mapper的代理方法开发时,有重要作用 -->
- <mapper namespace="test">
- <!-- 在映射文件中配置多个,sql语句 -->
- <!-- 按照id查询 -->
- <!-- 将sql语句封装到MapperStatement中,所以也将id 成为statement的Id -->
- <!-- paramerType:指定输入参数的类型。
- #{ } :代表占位符。
- #{id }:表示接受输入参数id的值,如果输入参数是简单类型,#{ }中的参数名可以任意
- ,可以是value或是其他值
- resultType:表示sql输出结果的所映射的Javabean的对象类型,resultType指定将单条记录映射成Java对像-->
- <select id="findUserById" parameterType="int" resultType="cn.edu.hpu.ssm.po.User">
- SELECT * FROM USER WHERE id = #{value}
- </select>
- </mapper>
2.Dao接口:
[java] view plain copy
- Public interface UserDao {
- public User getUserById(int id) throws Exception;
- }
3.Dao接口的实现
[java] view plain copy
- Public class UserDaoImpl implements UserDao {
- //通过构造函数注入SqlSessionFactory
- public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
- this.setSqlSessionFactory(sqlSessionFactory);
- }
- private SqlSessionFactory sqlSessionFactory;
- @Override
- public User getUserById(int id) throws Exception {
- SqlSession session = sqlSessionFactory.openSession();
- User user = null;
- try {
- //通过sqlsession调用selectOne方法获取一条结果集
- //参数1:指定定义的statement的id,参数2:指定向statement中传递的参数
- user = session.selectOne("test.findUserById", 1);
- System.out.println(user);
- } finally{
- session.close();
- }
- return user;
- }
- }
通过上面的例子,我们可以总结:
原始Dao开发存在以下问题:
Dao的方法存在重复代码,:通过sqlSessionFactory创建SqlSession,调用sqlSession数据库的操作方法。
调用sqlSession操作数据库的方法(第一个参数)时,硬编码,不利于系统的维护。
SqlSessionFactory的使用范围:
通过SQLSessionFactoryBuilder创建会话工厂SQLSessionFactory。将SQLSessionFactoryBuilder当做一个工具类来使用即可,不需要使用单例模式去管理。
通过SQLSessionFactory创建sqlSession,使用单例模式管理SQLSessionFactory,(工厂一旦被创建,使用一个实例)。将来mybatis与spring整合后,使用单例模式来管理sqlSessionFactory。
sqlSession是线程不安全的,在sqlsession中不但存在操作数据库的方法,还有数据域属性。sqlSession最佳应用场合,是在方法体内,定义成局部变量使用。
2.Mapper代理的方式:
mapper动态代理实现的原理:
mapper接口开发方式,只需要程序员编写mapper接口(相当于Dao接口),有mybatis框架根据接口定义创建接口的动态代理对象,代理的方法体与上面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的类型相同
1.Mapper.xml写法:(与上面User.xml不同的是namespace做了定义)
[html] view plain copy
- <?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进行分类化管理,sql隔离
- 注意:在使用mapper的代理方法开发时,有重要作用
- namespace命名必须与Mapper接口的路径相同 -->
- <mapper namespace="cn.edu.hpu.ssm.mapper.UserMapper">
- <!-- 按照id查询 -->
- <!-- 将sql语句封装到MapperStatement中,所以也将id 成为statement的Id -->
- <!-- paramerType:指定输入参数的类型。
- #{ } :代表占位符。
- #{id }:表示接受输入参数id的值,如果输入参数是简单类型,#{ }中的参数名可以任意
- ,可以是value或是其他值
- resultType:表示sql输出结果的所映射的Javabean的对象类型,resultType指定将单条记录映射成Java对像-->
- <select id="findUserById" parameterType="int" resultType="User">
- SELECT * FROM USER WHERE id = #{value}
- </select>
- </mapper>
2.mapper.java(接口文件)
[java] view plain copy
- package cn.edu.hpu.ssm.mapper;
- import java.util.List;
- import java.util.Map;
- import cn.edu.hpu.ssm.po.User;
- import cn.edu.hpu.ssm.po.UserCustom;
- import cn.edu.hpu.ssm.po.UserQueryVo;
- public interface UserMapper {
- //返回值类型必须与mapper.xml中resultType类型相同
- //形参必须与mapper.xml中的parameterType类型相同
- //mapper.java接口中的方法名和mapper.xml中statement的id一致
- public User findUserById(int id) throws Exception;
- }
3.测试文件:(通过junit)
[java] view plain copy
- public class MapperTest {
[java] view plain copy
- private SqlSessionFactory sqlSessionFactory;
- @Before
- public void setUp() throws Exception {
- String resource = "SqlMapConfig.xml";
- InputStream input = Resources.getResourceAsStream(resource);
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(input);
- }
[java] view plain copy
- /**
- * 通过id查询
- * @throws Exception
- */
- @Test
- public void testFindUserById() throws Exception {
- SqlSession session = sqlSessionFactory.openSession();
- //通过session自动创建mapper代理对象
- UserMapper userMap = session.getMapper(UserMapper.class);
- User user = userMap.findUserById(1);
- System.out.println(user);
- }
[java] view plain copy
- }
4.对Mapper动态代理的一个小结:
1.使用mapper代理时,输入参数类型可以使用pojo的包装对象,或是mapper对象,保证dao的同性。
2.selectOne和selectList
动态代理对象通过sqlsession.selectOne和sqlsession.selectList,是通过对返回值类型进行判断而选择调用哪一个方法。如果返回单个对象则调用selectOne,返回集合对象则调用selectList