原始DAO开发
SqlSession使用范围
SqlSessionFactoryBuilder
- 通过SqlSessionFactoryBuilder创建会话工厂SqlSessionFactory
- 将SqlSessionFactoryBuilder当成一个工具类使用即可,不需要使用单例管理SqlSessionFactoryBuilder。
- 在需要创建SqlSessionFactory时候,只需要new一次SqlSessionFactoryBuilder即可。
SqlSessionFactory
- 通过SqlSessionFactory创建SqlSession,使用单例模式管理sqlSessionFactory(工厂一旦创建,使用一个实例)。
- 将来mybatis和spring整合后,使用单例模式管理sqlSessionFactory。
SqlSession
- SqlSession是一个面向用户(程序员)的接口。
- SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象)、。
- SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性。
- SqlSession最佳应用场合在方法体内,定义成局部变量使用。

public class User { // private String id; private Integer id; private String username;// 用户姓名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 /* public String getId() { return id; } public void setId(String id) { this.id = id; }*/ public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", sex='" + sex + '\'' + ", birthday=" + birthday + ", address='" + address + '\'' + '}'; } }
User.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语句进行分类化管理,隔离 paramterType:参数类型 java类型 pojo(保存的时候) resultType:结果类型 数据库的字段名必须和实体类的属性名一致 #{id}:一个占位符 --> <mapper namespace="test"> <!-- id:标识配置文件中唯一的sql 一般称为statement的id --> <select id="findUserById" parameterType="int" resultType="b_dao_origin.pojo.User"> SELECT * FROM USER WHERE id=#{id} </select> </mapper>

public interface UserDao { /** * 根据id查询 * @param id * @return */ public User getUserById(Integer id); }
UserDaoImpl
1 public class UserDaoImpl implements UserDao { 2 private SqlSessionFactory sqlSessionFactory; 3 //通过构造方法注入sqlSessionFactory 4 public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { 5 this.sqlSessionFactory = sqlSessionFactory; 6 } 7 8 /** 9 * 根据id查询 10 * @param id 11 * @return 12 */ 13 @Override 14 public User getUserById(Integer id) { 15 SqlSession sqlSession = sqlSessionFactory.openSession(); 16 User user = sqlSession.selectOne("test.findUserById", id); 17 return user; 18 } 19 }

public class Demo { SqlSessionFactory sqlSessionFactory = null; @Before public void before() throws IOException { //通过流的方式得到核心配置文件 InputStream inputStream = Resources.getResourceAsStream("b_dao_origin/sqlMapConfig.xml"); //通过配置文件创建session工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void test(){ //如果使用代理增强了方法就不能用UserDaoImpl 要用UserDao UserDaoImpl userDao = new UserDaoImpl(sqlSessionFactory); User userById = userDao.getUserById(1); System.out.println(userById); } }
存在的问题:
1.如果DAO层有很多方法,实现类中就会出现很多重复的代码。
2.调用sqlsession方法时将statemnt的id硬编码了,不利于维护。
3.调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
Mapper动态代理方式
实现原理:
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
需要遵循的规范:
(1)Mapper接口和Mapper.xml需要放置在一个目录下,且同名
(2)Mapper.xml中的namespace值等于Mapper接口的全路径
(3)Mapper接口的方法名和statement Id一致
(4)Mapper接口的参数类型和statement paramterType类型一致
(5)Mapper接口的返回值和statement resultType类型一致(注意:返回值可能是list)
注意:mapper接口只能传递一个参数(尽量保证原子操作)、当需要传递多个参数的时候,可以使用pojo或者包装类型pojo,hashmap
Mapper接口:
public interface UserMapper { /** * 根据id查询 * @param id * @return */ public List<User> getUserById(Integer id); /** * 通过姓氏进行模糊查询 * @param name * @return */ public List<User> getUsersByName(String name); }
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:mapper接口的全路径 paramterType:参数类型 java类型 pojo(保存的时候) resultType:结果类型 数据库的字段名必须和实体类的属性名一致 #{id}:一个占位符 --> <mapper namespace="c_dao_mapper.mapper.UserMapper"> <select id="getUserById" parameterType="int" resultType="user"> SELECT * FROM USER WHERE id=#{id} </select> <select id="getUsersByName" parameterType="string" resultType="user"> SELECT * FROM USER WHERE username LIKE #{value}"%" </select> </mapper>
在sqlMapConfig.xml中配置别名和引入映射文件UserMapper.xml
<typeAliases> <!-- type:类型的全路径 alias:对应类型的别名 建议类名首字母小写 --> <!-- <typeAlias type="c_dao_mapper.pojo.User" alias="user"></typeAlias>--> <!-- 扫描指定的包名 别名:类名,默认首字母小写 --> <package name="c_dao_mapper.pojo"></package> </typeAliases> <!--引入映射文件--> <mappers> <!-- <mapper resource="c_dao_mapper/mapper/UserMapper.xml"></mapper> 可以通过xml文件找到class<mapper class="c_dao_mapper.mapper.UserMapper"></mapper>--> <!--批量加载 只能在mapper方式开发的时候用--> <package name="c_dao_mapper.mapper"></package> </mappers>
测试类:
public class Demo { SqlSessionFactory sqlSessionFactory = null; @Before public void before() throws IOException { //通过流的方式得到核心配置文件 InputStream inputStream = Resources.getResourceAsStream("c_dao_mapper/sqlMapConfig.xml"); //通过配置文件创建session工厂 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void test(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); //生成usermapper代理对象 会实现UserMapper接口里面的方法 //如果public User getUserById(Integer id); //代理对象就会调用selectone方法 //如果public List<User> getUserById(Integer id); //代理对象就会调用selectList方法 List<User> userById = mapper.getUserById(1); System.out.println(userById); } //模糊查询 @Test public void test2(){ SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.getUsersByName("w"); System.out.println(userList); } }