1.背景
在上篇中我们使用了MyBatis实现简单的增删改查,并没有进行dao层的封装,所以在这里我们进行dao层开发:
(1)传统的jdbc dao层开发(写dao接口,实现dao接口类)
(2)mapper代理方法 (只需要写mapper接口类,相当于dao接口类)
在Mybatis操作的时候,我们使用的是SqlSession 来进行数据库操作,其中SqlSession的使用范围:
通过SqlSessionFactoryBuilder创建SqlSessionFactory ,而SqlSession通过SqlSessionFactory 创建,所以使用单例模式管理SqlSessionFactory,将来使用mybatis和spring整合后,使用单例模式管理SqlSessionFactory;
SqlSession的作用是:
1)提供接口,很多操作数据库的方法,如:selectOne ,selectList
2)线程不安全,在sqlSession实现类中除了有接口中的方法,还有数据域的属性;
3)最佳应用的场合在方法体内,定义成局部变量使用。
2.原始dao开发实现
(1)dao接口
- package mybatie.dao;
-
- import mybatis.po.FClient;
-
-
-
-
-
-
-
-
-
- public interface ClientDao {
-
- FClient findClientById(int id) throws Exception;
-
- void updateClient(FClient f) throws Exception;
-
- void deleteClient(int id) throws Exception;
-
- void insertClient(FClient f) throws Exception;
-
- }
(2)实现dao接口
实现数据库操作的几个方法:
- package mybatie.dao;
-
- import mybatis.po.FClient;
- import oracle.net.aso.s;
-
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
-
- public class ClientDaoImp implements ClientDao {
-
- private SqlSessionFactory sqlSessionFactory;
-
- public ClientDaoImp(SqlSessionFactory sqlSessionFactory) {
- this.sqlSessionFactory = sqlSessionFactory;
- }
-
- @Override
- public FClient findClientById(int id) {
-
- SqlSession sqlSession = sqlSessionFactory.openSession();
- FClient c = sqlSession.selectOne("test.findClientById", id);
- sqlSession.close();
- return c;
- }
-
- @Override
- public void updateClient(FClient f) {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- sqlSession.update("test.updateClient",f);
- sqlSession.commit();
- sqlSession.close();
- }
-
- @Override
- public void deleteClient(int id) {
- SqlSession session = sqlSessionFactory.openSession();
- session.delete("test.deleteClient", id);
- session.commit();
- session.close();
- }
-
- @Override
- public void insertClient(FClient f) {
- SqlSession session = sqlSessionFactory.openSession();
- session.insert("test.insertClient", f);
- session.commit();
- session.close();
- }
-
-
- }
(3)测试类
- public class TestClient {
-
- private SqlSessionFactory sqlSessionFactory;
-
- @Before
- public void setUp() throws Exception {
- InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
- }
-
- @Test
- public void test() {
- fail("Not yet implemented");
- }
-
- @Test
- public void findClientById() throws Exception {
-
- ClientDao clientDao = new ClientDaoImp(sqlSessionFactory);
- FClient c = clientDao.findClientById(1);
- System.out.println(c);
- }
-
- }
(4)原始的dao层遇到的问题
1)dao接口实现类方法中存在大量的模板方法,设想能否将这些代码提取出来
2)调用sqlsession方法的时候将statement存在硬编码
3)调用sqlsession的方法的时候,传入参数为Object 类型,及时传入错误,也不会报错
3.使用Mapper代理的方式实现
基本步骤为 :
1)编写mapper.xml映射文件
2)编写Mapper接口,相当于dao接口
3)mybatis可以自动生成mapper接口的实现类代理对象
(1)实现Mapper映射文件
mapper.xml 规范 :
1)namespace 等于mapper接口地址
2)mapper.Java 接口中的方法和mapper.xml中的statement 的id一致
3)mapper.java 接口中的方法的参数和mapper.xml中的statement 的paramterType类型一致
4)mapper.java 接口中的方法的返回值和mapper.xml中的statement的resultType类型一致
总结 :mapper.xml实现的规范,就是对SqlSession接口中的方法进行统一的生成
比如 :
- <?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">
-
-
-
-
- <mapper namespace="mybatie.mapper.ClientMapper">
-
-
- <!-- 通过select 执行数据库查询 id:表示映射文件的sql, 将sql语句封装到mappedStatement对象中,所以将id称为statement的id
- #{}: 表示一个占位符,相当于jdbc中的? parameterType : 指定参数类型,比如指定为int #{id} : 其中的id表示接入输入的参数,参数名称就是id,如果输入的参数是简单类型
- #{}中参数名可以任意,可以value或其他名称; resultType :指定sql输出的结果的映射java对象类型,select指定的resultType表示将单条记录映射成java对象 -->
-
- <select id="findClientById" parameterType="int" resultType="mybatis.po.FClient">
- select * from f_client where id=#{id}
- </select>
-
- <!-- 根据用户名模糊查询 resultType :指定的单条记录所映射的java对象类型 #{} 表示占位符 ${}:表示拼接sql串,将接收到的参数内容不加任何修饰拼接在sql中,使用${}拼接,引起sql注入
- ${value} :接入输入参数的内容,如果传入类型是简单类型,${}简单的 -->
- <select id="findClientByName" parameterType="java.lang.String"
- resultType="mybatis.po.FClient">
- select *from f_client where username like '%${value}%'
- </select>
-
-
- <select id="insertClient" parameterType="mybatis.po.FClient"
- resultType="java.lang.Integer">
- insert into
- f_client(id,username,client_certificate_no,born_date,family_register_address,now_address,contact_mode,urgency_contact_mode,create_date)
- values (#{id},
- #{username},#{client_certificate_no},#{born_date},#{family_register_address},#{now_address},#{contact_mode},#{urgency_contact_mode},#{create_data})
- </select>
-
-
- <delete id="deleteClient" parameterType="int">
- delete from f_client where id=#{id}
- </delete>
-
-
- <update id="updateClient" parameterType="mybatis.po.FClient">
-
- update f_client set
- username=#{username},client_certificate_no=#{client_certificate_no},born_date=#{born_date},family_register_address=#{family_register_address},now_address=#{now_address},contact_mode=#{contact_mode},urgency_contact_mode=#{urgency_contact_mode}
- where id=#{id}
-
- </update>
-
-
- </mapper>
(2)mapper接口
注意接口定义的和Mapper.xml对比下,看看mapper.xml的 规范!!
- package mybatie.mapper;
-
- import java.util.List;
-
- import mybatis.po.FClient;
-
-
-
-
-
-
-
-
- public interface ClientMapper {
-
- public FClient findClientById(int id) throws Exception;
-
- public void updateClient(FClient f) throws Exception;
-
- public void deleteClient(int id) throws Exception;
-
- public int insertClient(FClient f) throws Exception;
-
- public List<FClient> findClientByName(String name) throws Exception;
- }
(3)测试
- private SqlSessionFactory sqlfactory;
-
- @Before
- public void setUp() throws Exception {
- InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
- sqlfactory=new SqlSessionFactoryBuilder().build(is);
- }
-
- @Test
- public void testFindClientById() throws Exception {
- SqlSession session = sqlfactory.openSession();
- ClientMapper mapper = session.getMapper(ClientMapper.class);
- FClient fc = mapper.findClientById(1);
- System.out.println(fc);
- session.close();
- }
4.一些问题
(1)代理对象内部调用selectOne或 selectList
如果mapper方法返回单个pojo对象,代理对象内部通过selectOne查询数据库;
如果mapper方法返回集合对象,代理对象内部通过内部通过selectList查询数据库;
否则会报错误。
(2) mapper接口方法参数只能有一个是否影响系统开发
系统框架中,dao层的代码是否是被业务层公用的,即使mapper接口只有一个参数,可以使用包装
类型pojo满足不同业务方法需求;
注意:持久层方法的参数可以包装类型,map,service方法中建议不要使用包装类型,因为不利于
业务层的可扩展性。
1.背景
在上篇中我们使用了MyBatis实现简单的增删改查,并没有进行dao层的封装,所以在这里我们进行dao层开发:
(1)传统的jdbc dao层开发(写dao接口,实现dao接口类)
(2)mapper代理方法 (只需要写mapper接口类,相当于dao接口类)
在Mybatis操作的时候,我们使用的是SqlSession 来进行数据库操作,其中SqlSession的使用范围:
通过SqlSessionFactoryBuilder创建SqlSessionFactory ,而SqlSession通过SqlSessionFactory 创建,所以使用单例模式管理SqlSessionFactory,将来使用mybatis和spring整合后,使用单例模式管理SqlSessionFactory;
SqlSession的作用是:
1)提供接口,很多操作数据库的方法,如:selectOne ,selectList
2)线程不安全,在sqlSession实现类中除了有接口中的方法,还有数据域的属性;
3)最佳应用的场合在方法体内,定义成局部变量使用。
2.原始dao开发实现
(1)dao接口
- package mybatie.dao;
-
- import mybatis.po.FClient;
-
-
-
-
-
-
-
-
-
- public interface ClientDao {
-
- FClient findClientById(int id) throws Exception;
-
- void updateClient(FClient f) throws Exception;
-
- void deleteClient(int id) throws Exception;
-
- void insertClient(FClient f) throws Exception;
-
- }
(2)实现dao接口
实现数据库操作的几个方法:
- package mybatie.dao;
-
- import mybatis.po.FClient;
- import oracle.net.aso.s;
-
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
-
- public class ClientDaoImp implements ClientDao {
-
- private SqlSessionFactory sqlSessionFactory;
-
- public ClientDaoImp(SqlSessionFactory sqlSessionFactory) {
- this.sqlSessionFactory = sqlSessionFactory;
- }
-
- @Override
- public FClient findClientById(int id) {
-
- SqlSession sqlSession = sqlSessionFactory.openSession();
- FClient c = sqlSession.selectOne("test.findClientById", id);
- sqlSession.close();
- return c;
- }
-
- @Override
- public void updateClient(FClient f) {
- SqlSession sqlSession=sqlSessionFactory.openSession();
- sqlSession.update("test.updateClient",f);
- sqlSession.commit();
- sqlSession.close();
- }
-
- @Override
- public void deleteClient(int id) {
- SqlSession session = sqlSessionFactory.openSession();
- session.delete("test.deleteClient", id);
- session.commit();
- session.close();
- }
-
- @Override
- public void insertClient(FClient f) {
- SqlSession session = sqlSessionFactory.openSession();
- session.insert("test.insertClient", f);
- session.commit();
- session.close();
- }
-
-
- }
(3)测试类
- public class TestClient {
-
- private SqlSessionFactory sqlSessionFactory;
-
- @Before
- public void setUp() throws Exception {
- InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
- sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
- }
-
- @Test
- public void test() {
- fail("Not yet implemented");
- }
-
- @Test
- public void findClientById() throws Exception {
-
- ClientDao clientDao = new ClientDaoImp(sqlSessionFactory);
- FClient c = clientDao.findClientById(1);
- System.out.println(c);
- }
-
- }
(4)原始的dao层遇到的问题
1)dao接口实现类方法中存在大量的模板方法,设想能否将这些代码提取出来
2)调用sqlsession方法的时候将statement存在硬编码
3)调用sqlsession的方法的时候,传入参数为Object 类型,及时传入错误,也不会报错
3.使用Mapper代理的方式实现
基本步骤为 :
1)编写mapper.xml映射文件
2)编写Mapper接口,相当于dao接口
3)mybatis可以自动生成mapper接口的实现类代理对象
(1)实现Mapper映射文件
mapper.xml 规范 :
1)namespace 等于mapper接口地址
2)mapper.Java 接口中的方法和mapper.xml中的statement 的id一致
3)mapper.java 接口中的方法的参数和mapper.xml中的statement 的paramterType类型一致
4)mapper.java 接口中的方法的返回值和mapper.xml中的statement的resultType类型一致
总结 :mapper.xml实现的规范,就是对SqlSession接口中的方法进行统一的生成
比如 :
- <?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">
-
-
-
-
- <mapper namespace="mybatie.mapper.ClientMapper">
-
-
- <!-- 通过select 执行数据库查询 id:表示映射文件的sql, 将sql语句封装到mappedStatement对象中,所以将id称为statement的id
- #{}: 表示一个占位符,相当于jdbc中的? parameterType : 指定参数类型,比如指定为int #{id} : 其中的id表示接入输入的参数,参数名称就是id,如果输入的参数是简单类型
- #{}中参数名可以任意,可以value或其他名称; resultType :指定sql输出的结果的映射java对象类型,select指定的resultType表示将单条记录映射成java对象 -->
-
- <select id="findClientById" parameterType="int" resultType="mybatis.po.FClient">
- select * from f_client where id=#{id}
- </select>
-
- <!-- 根据用户名模糊查询 resultType :指定的单条记录所映射的java对象类型 #{} 表示占位符 ${}:表示拼接sql串,将接收到的参数内容不加任何修饰拼接在sql中,使用${}拼接,引起sql注入
- ${value} :接入输入参数的内容,如果传入类型是简单类型,${}简单的 -->
- <select id="findClientByName" parameterType="java.lang.String"
- resultType="mybatis.po.FClient">
- select *from f_client where username like '%${value}%'
- </select>
-
-
- <select id="insertClient" parameterType="mybatis.po.FClient"
- resultType="java.lang.Integer">
- insert into
- f_client(id,username,client_certificate_no,born_date,family_register_address,now_address,contact_mode,urgency_contact_mode,create_date)
- values (#{id},
- #{username},#{client_certificate_no},#{born_date},#{family_register_address},#{now_address},#{contact_mode},#{urgency_contact_mode},#{create_data})
- </select>
-
-
- <delete id="deleteClient" parameterType="int">
- delete from f_client where id=#{id}
- </delete>
-
-
- <update id="updateClient" parameterType="mybatis.po.FClient">
-
- update f_client set
- username=#{username},client_certificate_no=#{client_certificate_no},born_date=#{born_date},family_register_address=#{family_register_address},now_address=#{now_address},contact_mode=#{contact_mode},urgency_contact_mode=#{urgency_contact_mode}
- where id=#{id}
-
- </update>
-
-
- </mapper>
(2)mapper接口
注意接口定义的和Mapper.xml对比下,看看mapper.xml的 规范!!
- package mybatie.mapper;
-
- import java.util.List;
-
- import mybatis.po.FClient;
-
-
-
-
-
-
-
-
- public interface ClientMapper {
-
- public FClient findClientById(int id) throws Exception;
-
- public void updateClient(FClient f) throws Exception;
-
- public void deleteClient(int id) throws Exception;
-
- public int insertClient(FClient f) throws Exception;
-
- public List<FClient> findClientByName(String name) throws Exception;
- }
(3)测试
- private SqlSessionFactory sqlfactory;
-
- @Before
- public void setUp() throws Exception {
- InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
- sqlfactory=new SqlSessionFactoryBuilder().build(is);
- }
-
- @Test
- public void testFindClientById() throws Exception {
- SqlSession session = sqlfactory.openSession();
- ClientMapper mapper = session.getMapper(ClientMapper.class);
- FClient fc = mapper.findClientById(1);
- System.out.println(fc);
- session.close();
- }
4.一些问题
(1)代理对象内部调用selectOne或 selectList
如果mapper方法返回单个pojo对象,代理对象内部通过selectOne查询数据库;
如果mapper方法返回集合对象,代理对象内部通过内部通过selectList查询数据库;
否则会报错误。
(2) mapper接口方法参数只能有一个是否影响系统开发
系统框架中,dao层的代码是否是被业务层公用的,即使mapper接口只有一个参数,可以使用包装
类型pojo满足不同业务方法需求;
注意:持久层方法的参数可以包装类型,map,service方法中建议不要使用包装类型,因为不利于
业务层的可扩展性。