Mybatis的Dao【mapper代理方式实现】
- Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。
- 不过要实现mapper代理的开发方式,需要遵循一些开发规范。
开发规范
1. mapper接口的全限定名要和mapper映射文件的namespace的值相同。
2. mapper接口的方法名称要和mapper映射文件中的statement的id相同;
3. mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。
4. mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;
通过规范式的开发mapper接口,可以解决原始dao开发当中存在的问题:
模板代码已经去掉;
剩下去不掉的操作数据库的代码,其实就是一行代码。这行代码中硬编码的部分,通过第一和第二个规范就可以解决。
- SqlSqlMapConfig中添加映射配置文件
- 测试
private SqlSession sqlSession;
@Before
public void init() throws IOException {
// 读取配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 创建sqlSessionFactory
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(inputStream);
// 创建sqlSession
sqlSession = sqlSession = ssf.openSession();
}
@After
public void after() {
sqlSession.close();
}
设置全局配置文件
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
加载mapper的方式
-
< mapper resource=" "/>
使用相对于类路径的资源
如:< mapper resource=“sqlmap/User.xml” /> -
< mapper class=’’/>
使用mapper接口的全限定名
如:< mapper class=“com.hlk.mapper.UserMapper”/> -
< package name=’’/>(推荐)
注册指定包下的所有映射文件
如:< package name=“cn.gyf.mybatis.mapper”/>
注意:此种方法要求mapper接口和mapper映射文件要名称相同,且放到同一个目录下; -
注解开发
UserMapper.xml还是要加载到全局配置文件中,但其中的
<select id="findUserById" parameterType="int" resultType="User">
SELECT * FROM USER WHERE id = #{id}
</select>
可以删除
Mybatis的映射文件详解
指定输入参数的java类型,可以使用别名或者类的全限定名。它可以接收简单类型,POJO对象、HashMap。
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
需求
综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)。
vo:键值对对象,相对于kv
po:persist object 持久化对象
pojo:简单的java对象
entity:实体
输出映射 resultType/resultMap
-
resultType
- 使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功。
- 如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象。
- 如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象。
-
输出简单类型
当输出结果只有一列时,可以使用ResultType指定简单类型作为输出结果类型。
- UserMapper.java
public interface UserMapper {
int getCountBySex(UserQueryVo vo);
}
- UserMapper.xml
<select id="getCountBySex" parameterType="userQueryVo" resultType="int">
SELECT COUNT(*) FROM USER WHERE sex = #{user.sex}
</select>
- Test.java
@Test
public void test10() throws IOException {
// 通过sqlSession获取mapper的代理实例类
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
UserQueryVo vo = new UserQueryVo();
User user = new User();
user.setSex("1");
vo.setUser(user);
int count = mapper.getCountBySex(vo);
System.out.println("该性别人数:" + count);
}
User findUser(UserQueryVo userQueryVo);// 接口方法
<select id="findUserList" parameterType="userQueryVo" resultType="user">
SELECT * FROM USER WHERE address = #{user.address}
</select>
List<User> findUserList(UserQueryVo userQueryVo);// 接口方法
<select id="findUserList" parameterType="userQueryVo" resultType="user">
SELECT * FROM USER WHERE address = #{user.address}
</select>
总结:
-
输出单个pojo对象和pojo列表时,mapper映射文件中的resultType的类型是一样的,mapper接口的方法返回值不同。
-
同样的mapper映射文件,返回单个对象和对象列表时,mapper接口在生成动态代理的时候,会根据返回值的类型,决定调用selectOne方法还是selectList方法。
-
resultMap
-
如果查询出来的列名和属性名不一致,通过定义一个resultMap将列名和pojo属性名之间作一个映射关系。
- 1、 定义resultMap
- 2、使用resultMap作为statement的输出映射类型
-
UserMapper.xml
<resultMap id="userResultMap" type="user">
<id property="id" column="id_"/>
<result property="username" column="username_"/>
<result property="address" column="address_"/>
</resultMap>
<!--由于POJO的字段与属性名不同,所以通过resultMap来匹配-->
<select id="findUserByResultMap" parameterType="int" resultMap="userResultMap">
SELECT id id_,username username_,address address_ FROM USER WHERE id=#{id}
</select>
动态SQL
<!--动态SQL-->
<select id="findUser" parameterType="userQueryVo" resultType="user">
SELECT * FROM USER
<where>
<if test="user != null">
<if test="user.sex != null and user.sex != ''">
sex = #{user.sex}
</if>
<if test="user.address != null and user.address != ''">
AND address LIKE #{user.address}
</if>
</if>
</where>
</select>
<!--foreach标签-->
<select id="findUserByForEach" parameterType="userQueryVo" resultType="user">
SELECT * FROM USER
<where>
/*
[foreach标签]:表示一个foreach循环
[collection]:集合参数的名称,如果直接传入集合参数,则该处的参数名称只能填写list
[item]:每次遍历出来的对象
[open]:开始遍历时拼接的字符串
[close]:结束遍历时拼接的字符串
[separator]:遍历出的每个对象之间需要拼接的字符串
*/
<foreach collection="ids" item="id" open="id IN (" close=")" separator=",">
#{id}
</foreach>
</where>
</select>
- UserQuserVo.java
public class UserQueryVo {
private User user;
private List<Integer> ids;
public List<Integer> getIds() {
return ids;
}
}
- 测试
@Test
public void test2() {
UserQueryVo vo = new UserQueryVo();
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(5);
list.add(27);
vo.setIds(list);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> lists = mapper.findUserByForEach(vo);
for (User u : lists) {
System.out.println(u);
}
}
<!--foreach标签-->
<select id="findUserByList" parameterType="java.util.List" resultType="user">
SELECT * FROM USER
<where>
<foreach collection="list" item="id" open="id IN (" close=")" separator=",">
#{id}
</foreach>
</where>
</select>
Mybatis与Hibernate的区别
-
Mybatis技术特点:
好处:
1、 通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2、 学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
3、 由于直接编写SQL语句,所以灵活多变,代码维护性更好。
缺点:
4、 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
a) Mysql:limit
b) Oracle:rownum
5、 需要编写结果映射。 -
Hibernate技术特点:
好处:
1、 标准的orm框架,程序员不需要编写SQL语句。
2、 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
a) 以后,mysql数据迁移到oracle,只需要改方言配置
缺点:
3、 学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
4、 程序员不能自主的去进行SQL性能优化。 -
Mybatis应用场景:
需求多变的互联网项目,例如电商项目。 -
Hibernate应用场景:
需求明确、业务固定的项目,例如OA项目、ERP项目等