本文讲解SqlSession,并对两种方法(原始dao开发和mapper代理开发)分别做简单展示
SqlSession使用范围 
通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
SqlSession是一个面向用户(程序员)的接口。SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)。
SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
SqlSession最佳应用场合在方法体内,定义成局部变量使用。
原始dao开发方法 程序员需要写dao接口和dao实现类
dao接口 1 2 3 4 5 6 7 8 9 10 11 12 13 public  interface  UserDao           public  User findUserById (int  id)  throws  Exception          public  List<User> findUserByName (String name)  throws  Exception          public  void  insertUser (User user)  throws  Exception          public  void  deleteUser (int  id)  throws  Exception } 
dao接口实现类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 package  com.iot.mybatis.dao;import  com.iot.mybatis.po.User;import  org.apache.ibatis.session.SqlSession;import  org.apache.ibatis.session.SqlSessionFactory;import  java.util.List;public  class  UserDaoImpl  implements  UserDao               private  SqlSessionFactory sqlSessionFactory;     public  UserDaoImpl (SqlSessionFactory sqlSessionFactory)          this .sqlSessionFactory = sqlSessionFactory;     }     @Override      public  User findUserById (int  id)  throws  Exception          SqlSession sqlSession = sqlSessionFactory.openSession();         User user = sqlSession.selectOne("test.findUserById" ,id);                  sqlSession.close();         return  user;     }     @Override      public  List<User> findUserByName (String name)  throws  Exception          SqlSession sqlSession = sqlSessionFactory.openSession();         List<User> list = sqlSession.selectList("test.findUserByName" , name);                  sqlSession.close();         return  list;     }     @Override      public  void  insertUser (User user)  throws  Exception          SqlSession sqlSession = sqlSessionFactory.openSession();                  sqlSession.insert("test.insertUser" , user);                  sqlSession.commit();                  sqlSession.close();     }     @Override      public  void  deleteUser (int  id)  throws  Exception          SqlSession sqlSession = sqlSessionFactory.openSession();                  sqlSession.delete("test.deleteUser" , id);                  sqlSession.commit();                  sqlSession.close();     } } 
测试代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package  com.iot.mybatis.dao;import  java.io.InputStream;import  com.iot.mybatis.po.User;import  org.apache.ibatis.io.Resources;import  org.apache.ibatis.session.SqlSessionFactory;import  org.apache.ibatis.session.SqlSessionFactoryBuilder;import  org.junit.Before;import  org.junit.Test;public  class  UserDaoImplTest  	private  SqlSessionFactory sqlSessionFactory; 	 	@Before  	public  void  setUp ()  throws  Exception  		 		 		String resource = "SqlMapConfig.xml" ; 		 		InputStream inputStream = Resources.getResourceAsStream(resource); 		 		sqlSessionFactory = new  SqlSessionFactoryBuilder() 				.build(inputStream); 	} 	@Test  	public  void  testFindUserById ()  throws  Exception  		 		UserDao userDao = new  UserDaoImpl(sqlSessionFactory); 		 		User user = userDao.findUserById(1 ); 		System.out.println(user); 	} } 
总结原始dao开发问题 1.dao接口实现类方法中存在大量模板方法,设想能否将这些代码提取出来,大大减轻程序员的工作量。
2.调用sqlsession方法时将statement的id硬编码了
3.调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
mapper代理方法 程序员只需要mapper接口(相当 于dao接口)
程序员还需要编写mapper.xml映射文件
程序员编写mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类代理对象。
开发规范 
在mapper.xml中namespace等于mapper接口地址 
 
1 2 3 4 5 <mapper  namespace ="com.iot.mybatis.mapper.UserMapper" > 
mapper.java接口中的方法名和mapper.xml中statement的id一致
mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致。
mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致。
 
1 2 3 <select  id ="findUserById"  parameterType ="int"  resultType ="com.iot.mybatis.po.User" >     SELECT * FROM  user  WHERE id=#{value} </select > 
1 2 public  User findUserById (int  id)  throws  Exception
总结:以上开发规范主要是对下边的代码进行统一生成:
1 2 User user = sqlSession.selectOne("test.findUserById" , id); sqlSession.insert("test.insertUser" , user); 
代码 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 <?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 ="com.iot.mybatis.mapper.UserMapper" >                 <select  id ="findUserById"  parameterType ="int"  resultType ="com.iot.mybatis.po.User" >          SELECT * FROM  user  WHERE id=#{value}     </select >           <select  id ="findUserByName"  parameterType ="java.lang.String"  resultType ="com.iot.mybatis.po.User" >          SELECT * FROM user WHERE username LIKE '%${value}%'     </select >           <insert  id ="insertUser"  parameterType ="com.iot.mybatis.po.User" >                   <selectKey  keyProperty ="id"  order ="AFTER"  resultType ="java.lang.Integer" >            SELECT LAST_INSERT_ID()         </selectKey >          INSERT INTO user (username,birthday,sex,address)values (#{username},#{birthday},#{sex},#{address})                       </insert >           <delete  id ="deleteUser"  parameterType ="java.lang.Integer" >          delete from user where id=#{id}     </delete >           <update  id ="updateUser"  parameterType ="com.iot.mybatis.po.User" >          update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}         where id=#{id}     </update >  </mapper > 
1 2 3 <mappers >       <mapper  resource ="mapper/UserMapper.xml" />    </mappers > 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public  interface  UserMapper           public  User findUserById (int  id)  throws  Exception          public  List<User> findUserByName (String name)  throws  Exception          public  void  insertUser (User user)  throws  Exception          public  void  deleteUser (int  id)  throws  Exception          public  void  updateUser (User user) throws  Exception } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public  class  UserMapperTest      private  SqlSessionFactory sqlSessionFactory;            @Before        public  void  setup ()  throws  Exception                  String resource="SqlMapConfig.xml" ;                    InputStream inputStream = Resources.getResourceAsStream(resource);                    sqlSessionFactory=new  SqlSessionFactoryBuilder().build(inputStream);       }       @Test        public  void  testFindUserById ()  throws  Exception         SqlSession sqlSession=sqlSessionFactory.openSession();                    UserMapper userMapper=sqlSession.getMapper(UserMapper.class);                    User user=userMapper.findUserById(1 );           System.out.println(user.getUsername());       }   } 
一些问题总结 
代理对象内部调用selectOne或selectList
如果mapper方法返回单个pojo对象(非集合对象),代理对象内部通过selectOne查询数据库。 
如果mapper方法返回集合对象,代理对象内部通过selectList查询数据库。 
 
 
 
mapper接口方法参数只能有一个是否影响系统开发 
 
mapper接口方法参数只能有一个,系统是否不利于扩展维护?系统框架中,dao层的代码是被业务层公用的。即使mapper接口只有一个参数,可以使用包装类型的pojo满足不同的业务方法的需求。
注意:持久层方法的参数可以包装类型、map…等,service方法中建议不要使用包装类型(不利于业务层的可扩展)。