首页 > 代码库 > Mybatis学习(四)
Mybatis学习(四)
5.Mybatis开发dao
Mybatis在项目中主要使用的地方就是开发dao(数据访问层),所以下面讲解一下Mybatis开发dao的方法.有两种方式:原始dao开发方式、mapper代理开发方式(推荐).
5.1 需求
1.根据用户ID查询用户信息
2.根据用户名称模糊查询用户列表
3.添加用户
5.2 原始dao开发方式
及开发dao接口和dao实现
5.2.1 dao接口
1 package com.jxdd.mybatis.service; 2 3 import java.util.List; 4 5 import com.jxdd.mybatis.po.User; 6 7 public interface UserDao { 8 //1.根据用户ID查询用户信息 9 public User findUserById(int id); 10 //2.根据用户名称模糊查询用户列表 11 public List<User> findUserByName(String name); 12 //3.添加用户 13 public void insertUser(User user); 14 }
5.2.2 dao实现类
通过入门程序,大家可以看出,在测试代码中,有大量的重复代码。所以我们第一反应就是想给它抽取出共性的部分,但是SqlSession、SqlSessionFactory、SqlSessionFactoryBuilder有着各自的生命周期,因为这些生命周期的不同,抽取时要有针对性的处理。
所以在抽取之前,我们先来了解并总结下它们三个的生命周期。
1.SqlSessionFactoryBuilder
它的作用只是通过配置文件创建SqlSessionFactory,所以只要创建出SqlSessionFactory,它就可以销毁了。所以说,它的生命周期是在方法之内。
2.SqlSessionFactory
它的作用是创建SqlSession的工厂,工厂一旦创建,除非应用停掉,不要销毁。所以说它的生命周期是在应用范围内。这里可以通过单例模式来管理它。在mybatis整合spring之后,最好的处理方式是把SqlSessionFactory交由spring来做单例管理。
3.SqlSession
SqlSession是一个面向用户(程序员)的接口,它的默认实现是DefaultSqlSession。
Mybatis是通过SqlSession来操作数据库的。SqlSession中不仅包含要处理的SQL信息,还包括一些数据信息,所以说它是线程不安全的,因此它最佳的生命周期范围是在方法体之内。
1 package com.jxdd.mybatis.service.impl; 2 3 import java.util.List; 4 5 import org.apache.ibatis.session.SqlSession; 6 import org.apache.ibatis.session.SqlSessionFactory; 7 8 import com.jxdd.mybatis.po.User; 9 import com.jxdd.mybatis.service.UserDao; 10 11 public class UserDaoImpl implements UserDao { 12 //外部注入sqlSessionFactory实例 13 private SqlSessionFactory sqlSessionFactory; 14 15 public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { 16 this.sqlSessionFactory = sqlSessionFactory; 17 } 18 19 @Override 20 public User findUserById(int id) { 21 SqlSession sqlSession = sqlSessionFactory.openSession(); 22 //通过sqlsession调用增删改查方法 23 //第一个参数:statement的唯一标识,写法:namespace+"."+statementId 24 //第二个参数:输入参数 25 User user = sqlSession.selectOne("findUserById", id); 26 System.out.println(user); 27 //关闭资源 28 sqlSession.close(); 29 return user; 30 } 31 32 @Override 33 public List<User> findUserByName(String name) { 34 SqlSession sqlSession = sqlSessionFactory.openSession(); 35 //通过sqlsession调用增删改查方法 36 //第一个参数:statement的唯一标识,写法:namespace+"."+statementId 37 //第二个参数:输入参数 38 List<User> user = sqlSession.selectList("test.findUsersByName", name); 39 System.out.println(user); 40 //关闭资源 41 sqlSession.close(); 42 return user; 43 } 44 45 @Override 46 public void insertUser(User user) { 47 SqlSession sqlSession = sqlSessionFactory.openSession(); 48 //通过sqlsession调用增删改查方法 49 //第一个参数:statement的唯一标识,写法:namespace+"."+statementId 50 //第二个参数:输入参数 51 sqlSession.insert("test.insertUser", user); 52 //注意一定要commit 53 sqlSession.commit(); 54 //关闭资源 55 sqlSession.close(); 56 } 57 58 }
5.2.3 测试方法
1 package com.jxdd.mybatis.test; 2 3 import java.io.InputStream; 4 5 import org.apache.ibatis.io.Resources; 6 import org.apache.ibatis.session.SqlSessionFactory; 7 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 8 import org.junit.Before; 9 import org.junit.Test; 10 11 import com.jxdd.mybatis.po.User; 12 import com.jxdd.mybatis.service.UserDao; 13 import com.jxdd.mybatis.service.impl.UserDaoImpl; 14 15 public class UserDaoTest { 16 private SqlSessionFactory sqlSessionFactory; 17 @Before 18 public void setUp() throws Exception{ 19 //1.加载配置文件 20 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 21 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 22 } 23 @Test 24 public void findUserByIdTest(){ 25 //创建UserDao的对象 26 UserDao userDao = new UserDaoImpl(sqlSessionFactory); 27 userDao.findUserById(1); 28 } 29 }
5.2.4 问题总结
原始dao开发存在一些问题:
存在一定量的模板代码.比如:通过SqlSessionFactory创建SqlSession;调用SqlSession的方法操作数据库;关闭Sqlsession.
存在一些硬编码.调用SqlSession的方法操作数据库时,需要指定statement的id,这里存在硬编码.
5.3 Mapper代理开发方式(推荐)
Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。
不过要实现mapper代理的开发方式,需要遵循一些开发规范。
5.3.1 开发规范
1.mapper接口的全限定名要和mapper映射文件的namespace的值相同.
2.mapper接口的方法名称要和mapper映射文件中的statement的id相同.
3.mapper接口的参数只能有一个,且类型要和mapper映射文件中的statement的parameterType的值保持一致.
4.mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap的type值保持一致.
通过规范式的开发mapper接口,可以解决原始dao开发当中存在的问题:
1. 模板代码已经去掉;
2.剩下去不掉的操作数据库的代码,其实就是一行代码。这行代码中硬编码的部分,通过第一和第二个规范就可以解决。
5.3.2 mapper接口
1 package com.jxdd.mybatis.service; 2 3 import java.util.List; 4 5 import com.jxdd.mybatis.po.User; 6 7 public interface UserMapper { 8 //1.根据用户ID查询用户信息 9 public User findUserById(int id); 10 //2.根据用户名称模糊查询用户列表 11 public List<User> findUserByName(String name); 12 //3.添加用户 13 public void insertUser(User user); 14 }
5.3.3 mapper映射文件
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.jxdd.mybatis.service.UserMapper"> 6 <!-- 根据用户id查询用户信息 --> 7 <select id="findUserById" parameterType="int" resultType="com.jxdd.mybatis.po.User"> 8 SELECT * FROM USER WHERE id = #{id} 9 </select> 10 <!-- 根据用户名称模糊查询用户列表 --> 11 <select id="findUsersByName" parameterType="java.lang.String" resultType="com.jxdd.mybatis.po.User"> 12 SELECT * FROM USER WHERE username LIKE ‘%${value}%‘ 13 </select> 14 <!-- 添加用户 --> 15 <insert id="insertUser" parameterType="com.jxdd.mybatis.po.User"> 16 INSERT INTO USER(username,sex,birthday,address) VALUES (#{username},#{sex},#{birthday},#{address}) 17 </insert> 18 </mapper>
5.3.4 加载映射文件
1 <mappers> 2 <mapper resource="sqlmap/User.xml"/> 3 <mapper resource="mapper/UserMapper.xml"/> 4 </mappers>
5.3.5 测试
1 package com.jxdd.mybatis.test; 2 3 import java.io.InputStream; 4 5 import org.apache.ibatis.io.Resources; 6 import org.apache.ibatis.session.SqlSession; 7 import org.apache.ibatis.session.SqlSessionFactory; 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 9 import org.junit.Before; 10 import org.junit.Test; 11 12 import com.jxdd.mybatis.po.User; 13 import com.jxdd.mybatis.service.UserMapper; 14 15 public class UserMapperTest { 16 private SqlSessionFactory sqlSessionFactory; 17 @Before 18 public void setUp() throws Exception{ 19 //1.加载配置文件 20 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 21 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 22 } 23 @Test 24 public void findUserById(){ 25 //创建SqlSession对象 26 SqlSession sqlSession = sqlSessionFactory.openSession(); 27 //通过mybatis得到mapper接口的代理实现类 28 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 29 User user = userMapper.findUserById(1); 30 System.out.println(user); 31 //关闭资源 32 sqlSession.close(); 33 } 34 }
6.Mybatis全局配置文件
SqlMapConfig.xml是mybatis的全局配置文件,它的名称可以是任意命名的.
6.1全部配置内容
SqlMapConfig.xml的配置内容和顺序如下(顺序不能打乱)
Properties(属性)
Settings(全局参数设置)
typeAliases(类型别名)
typeHandler(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境信息集合)
environment(单个环境信息)
transactionManager(事务管理)
dataSource(数据源)
mappers(映射器)
6.2 常用配置详解
6.2.1 Properties
SqlMapConfig.xml文件中可以应用java属性文件中的配置信息
dp.properties 配置信息如下
db.driver=com.mysql.jdbc.Driver db.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8 db.username=root db.password=root
SqlMapConfig.xml使用properties标签后,如下所示:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <properties resource="db.properties"/> 7 <!-- 配置mybatis的环境信息 --> 8 <environments default="development"> 9 <environment id="development"> 10 <!-- 配置JDBC事务控制,由mybatis进行管理 --> 11 <transactionManager type="JDBC"></transactionManager> 12 <!-- 配置数据源,采用dbcp连接池 --> 13 <dataSource type="POOLED"> 14 <property name="driver" value="${db.driver}"/> 15 <property name="url" value="${db.url}"/> 16 <property name="username" value="${db.username}"/> 17 <property name="password" value="${db.password}"/> 18 </dataSource> 19 </environment> 20 </environments> 21 <mappers> 22 <mapper resource="sqlmap/User.xml"/> 23 <mapper resource="mapper/UserMapper.xml"/> 24 </mappers> 25 </configuration>
如果在<properties></properties>中添加<property name="db.username" value="http://www.mamicode.com/123"/>
其运行结果也不会有影响
使用${},可以引用已经加载的java配置文件中的信息。
注意:mybatis将按照下面的顺序加载属性:
1.Properties标签体内定义的属性首先被读取
2.Properties引用的属性会被读取,如果发现上面已经有同名的属性了,那后面会覆盖前面的值
3.parameterType接收的值会最后被读取,如果发现上面已经有同名的属性了,那后面会覆盖前面的值
所以说,mybatis读取属性的顺序由高到低分别是:parameterType接收的属性值、properties引用的属性、properties标签内定义的属性。
6.2.2 Settings
mybatis全局配置参数,全局参数将会影响mybatis的运行行为。
6.2.3 typeAliases
别名是使用是为了在映射文件中,更方便的去指定入参和结果集的类型,不再用写很长的一段全限定名。
6.2.3.1 MyBatis支持的别名
别名 映射的类型 _byte byte _long long _short short _int int _integer int _double double _float float _boolean boolean string String byte Byte long Long short Short int Integer integer Integer double Double float Float boolean Boolean date Date decimal BigDecimal bigdecimal BigDecimal
6.2.3.2 自定义别名
SqlMapConfig.xml配置信息如下:
1 <!-- 定义别名 --> 2 <typeAliases> 3 <!-- 单个定义别名 --> 4 <typeAlias type="com.jxdd.mybatis.po.User" alias="user"/> 5 6 <!-- 批量定义别名(推荐) --> 7 <!-- [name]:指定批量定义别名的类包,别名为类名(首字母大小写都可) --> 8 <package name="com.jxdd.mybatis.po"/> 9 </typeAliases>
6.2.4 mappers
6.2.4.1 <mapper resource=’’/>
使用相对于类路径的资源
如:<mapper resource="sqlmap/User.xml" />
6.2.4.2 <mapper url=’’/>
使用完全限定路径
如:<mapper url="file:///D:\workspace_spingmvc\mybatis01\config\sqlmap\User.xml" />
6.2.4.3 <mapper class=’’/>
使用mapper接口的全限定名
如:<mapper class="com.jxdd.mybatis.mapper.UserMapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下
6.2.4.5 <package name=’’/>(推荐)
注册指定包下的所有映射文件
如:<package name="com.jxdd.mybatis.mapper"/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下
Mybatis学习(四)