您现在的位置是:亿华云 > IT科技
Mybatis 中xml和注解映射,so easy啦
亿华云2025-10-09 03:30:05【IT科技】9人已围观
简介本文转载自微信公众号「Java后端技术全栈」,作者田维常。转载本文请联系Java后端技术全栈公众号。MyBatis 提供了XML配置和注解配置两种方式。今天就来搞搞这两种方式是如何实现的。MyBati
本文转载自微信公众号「Java后端技术全栈」,中注解作者田维常。映射转载本文请联系Java后端技术全栈公众号。中注解
MyBatis 提供了XML配置和注解配置两种方式。映射今天就来搞搞这两种方式是中注解如何实现的。
MyBatis 的映射真正强大在于它的语句映射,这是中注解它的魔力所在。由于它的映射异常强大,映射器的中注解 XML 文件就显得相对简单。如果拿它跟具有相同功能的映射JDBC 代码进行对比,你会立即发现省掉了将近 95% 的中注解代码。MyBatis 致力于减少使用成本,映射让用户能更专注于 SQL 代码。中注解
来自官网。映射
Mybatis映射九个顶级元素:
xml方式
九个顶级映射元素对应标签:
<mapper namespace="com.tian.mybatis.mapper.UserMapper"> <resultMap id="" type=""></resultMap> <sql id=""></sql> <cache blocking="" ></cache> <cache-ref namespace=""></cache-ref> <select id="selectUserById"></select> <insert id="insert" ></insert> <update id=""></update> <delete id=""></delete> </mapper>select详解
可以看得出,后面可选项还是蛮多的。下面是官网对每项的解释。
select使用案例
<?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.tian.mybatis.mapper.UserMapper"> <select id="selectUserById" resultType="com.tian.mybatis.entity.User" parameterType="int" > select * from m_user where id = #{ id} </select> </mapper> id必须在这个Mapper中是唯一的,可以被用来引用这条语句 ,源码库这个id必须与只对应的是XxxMapper.java中的方法,必须是一一对应。 返回类型:User类型,resultType:查询语句返回结果类型的完全限定名或别名。别名使用方式和parameterType是一样的。 参数:整形,表示查询语句传入参数的类型和完全限定名或别名。支持基础数据类型和复杂数据类型。#{ 参数名}:告诉MyBatis生成的PreparedStatement参数,相对于JDBC中,改参数被标识为‘?’。
别名与参数映射类型如下:
返回类型中别名的使用,注意:
如果是我们的entity类,那么resultType是无法使用别名的,只能使用resultMap才可以使用别名。
<?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.tian.mybatis.mapper.UserMapper"> <resultMap id="User" type="com.tian.mybatis.entity.User"/> <select id="selectUserById" resultMap="User" parameterType="int" > select * from m_user where id = #{ id} </select> </mapper>但是如果使用的上面映射表里,也可以直接使用别名。b2b信息网
数据库里有两条数据:
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"> <mapper namespace="com.tian.mybatis.mapper.UserMapper"> <select id="countUser" resultType="int"> select count(1) from m_user </select> </mapper>UserMapper.java
import com.tian.mybatis.entity.User; public interface UserMapper { int countUser(); }测试类:
public class MybatisApplication { public static final String URL = "jdbc:mysql://localhost.com:3306/mblog?useUnicode=true"; public static final String USER = "root"; public static final String PASSWORD = "123456"; public static void main(String[] args) { String resource = "mybatis-config.xml"; InputStream inputStream = null; SqlSession sqlSession = null; try { inputStream = Resources.getResourceAsStream(resource); //工厂模式 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取sql操作会话 sqlSession = sqlSessionFactory.openSession(); //构造对象(这里比较特殊,这里构造对象的方式后面会专门分享) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //查询统计 System.out.println(userMapper.countUser()); } catch (Exception e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } sqlSession.close(); } } }输出:2
当数据库表中的字段名和我们entity中的字段名不一致,怎么处理?
在实际开发中,这种常见是在所难免。我们可以使用下面的这种方式解决。
实体类User
public class User { private Integer id; private String userName; private Integer age; //set get toString方法这里就不贴了 }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"> <mapper namespace="com.tian.mybatis.mapper.UserMapper"> <resultMap id="User" type="com.tian.mybatis.entity.User"> <id column="id" property="id"/> <result column="name" property="userName"/> </resultMap> <select id="selectUserById" resultMap="User" parameterType="int" > select * from m_user where id = #{ id} </select> </mapper>继续使用我们前面的测试类进行测试:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class); System.out.println(userMapper.selectUserById(1));输出:User{ id=1, userName=tian, age=22}
注意:实体类的get set 和toString()方法这里给省略, 希望大家在使用的使用,使用快捷键很简单的就搞定了。
上面提到过resultType和resultMap,那么他们两到底有什么区别呢?
resultType和resultMap 有什么区别?
resultType:直接表示返回类型, 包括基本数据类型和复杂数据类型。 resultMap:外部resultMap定义的引用,通过对应的外部resultMap的id,表示结果映射到哪个resultMap上,一般用于字段名和属性名不一致的情况,或者需要做复杂的联合查询以便自由控制映射结果。两者的关联
当进行查询时,查询出来的每个字段都会放在一个Map里,当查询元素返回属性是resultType的时候,会将键值对取出赋所指定的属性。其实MyBatis的每个查询映射的返回类型都是resultMap,只是当我们使用resultType的时候,会自动把对应的值赋给所指定的对象属性,当使用resultMap时候,因为map不是很好的表示领域,我们就进一步的转化为对应的实体对象。resultMap主要作用于复杂的联合查询上。
resultMap的自动映射级别:默认级别为PARTIAL,也可以在settings更改值。
注意:resultType和resultMap本质是一样的,都是Map数据结构,但是二者不能同时存在。
增删改案例
insert
从这里可以知道,关于增加insert是没有返回值类型可以让我们指定的。默认返回int类型。
<insert id="insert" parameterType="com.tian.mybatis.entity.User"> INSERT INTO m_user(`name`,age) VALUES ( #{ userName},#{ age}) </insert>对应Mapper中的方法
int insert(User user);另外的update和delete类似,这里就没有必要逐一演示了。
注解方式
九个顶级映射元素对应注解:
其他部分注解是配合九个注解进行使用的。
select注解
把本地的UserMapper.xml删掉,然后改一下mybatis-config.xml,把其中的UserMapper.xml给注释掉。添加
<mapper class="com.tian.mybatis.mapper.UserMapper"/>UserMapper.java添加注解
public interface UserMapper { @Select("select * from m_user where id = #{ id}") User selectUserById(Integer id); }再次测试
User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1); System.out.println(user);输出:
User{ id=1, userName=null, age=22}从输出内容看到,userName为null,这也是因为和数据库表汇中的字段name不一致导致的,那么如何处理呢?
这么搞,再添加一个注解:
public interface UserMapper { @Select("select * from m_user where id = #{ id}") @Results( @Result(column = "name",property = "userName")) User selectUserById(Integer id); }输出:
User{ id=1, userName=tian, age=22}这样也就是在使用注解的时候,处理实体属性名和数据库表字段名不一样的问题的办法。
insert、update、delete同样也可以使用注解来搞定了。
@Insert、@Update、@Delete配上相应的SQL语句。
注解和xml是否可以共存?
<update id="updateAuthorIfNecessary"> update m_user <trim prefix="SET" suffixOverrides=","> <if test="userName != null and userName != "> `name` = #{ userName}, </if> <if test="gender != null and gender != 0"> gender = #{ gender}, </if> <if test="age != null and age != 0"> age = #{ age}, </if> </trim> where id=#{ id} </update>同时在UserMapper.java中的方法上添加注解
@Update("update m_user set `name` = #{ userName},gender = #{ gender},age = #{ age} where id=#{ id}") int updateAuthorIfNecessary(User user);再次中子星的时候回报异常的:
nested exception is java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.tian.mybatis.mapper.UserMapper.updateAuthorIfNecessary. please check file [D:\workspace\my_code\mybatis\target\classes\mapper\UserMapper.xml] and com/tian/mybatis/mapper/UserMapper.java (best guess)大致意思就是说,已经存在了,即就是不能同时使用xml和注解。二者选其一。
xml可以喝注解结合使用,但是得保证同一个方法不能同时存在xml和注解。
建议
简单的sql处理可以使用注解,复杂的sql使用xml。但是实际工作还得看你待的项目中有没有对这个进行规范化。
在项目中无非就三种:
1.全部必须使用xml方式。
2.全部必须使用注解方式。
3.可以同时使用xml和注解。
高级映射
association
映射到JavaBean的某个复杂的”数据类型”属性,仅处理一对一的关联关系。
<resultMap type="com.tian.mybatis.entity.User" id="userMapRole"> <id column="id" property="id" /> <result column="name" property="userName" /> <result column="age" property="age" /> <association property="role" javaType="UserRole"> <id column="id" property="id" /> <result column="roleName" property="roleName" /> </association> </resultMap>association的属性节点:
property:映射数据库列的实体对象属性名。 javaType:完整的java类名和限定名。propert所映射的属性的类型。子元素
id:一般为映射主键,可以提高性能。 result: column:映射的数据库的字段名。 property:映射的数据列对应的实体对象属性。collection
映射到JavaBean的某个复杂的”数据类型”属性,这个属性是一个集合列表,处理一对多的关联关系。
<resultMap type="com.tian.mybatis.entity.User" id="userMapAddress"> <id column="id" property="id"/> <result column="name" property="userName"/> <collection property="lists" ofType="UserAddress"> <id column = "id" property = "id"> <result column="addressDesc" property="addressDesc"/> </collection> </resultMap>ofType:完整的Java类名和限定名。propert所映射的属性的类型。
其余和association基本一致。
association和collection都具备延迟加载功能。
延迟加载:先从单表查询,需要时再查关联表,大大的提高了数据库性能,因为相对来说单表查询比多表查询要快。
xml和注解的关系
上面我们已经讲了两种方式的实现,下面来对比一下,两种方式的关系:
xml方式
必须有个一个XxxMapper.xml与之对应,方法名对应xml中的id,方法入参和方法出参都必须对应起来,很容易出问题。我们在开发的时候有的是可以使用代码生成器生成,但是有的是必须自己手写,有的公司也是要求必须手写,所以这里需要注意。
注解方式
不需要XxxMapper.xml文件,只需要在对应XxxMapper.java中的方法上加上注解就搞定了,但是这里是有坑的。毕竟把sql放到了我们的Java代码里了。
优缺点
xml方式: 增加了xml文件,修改麻烦,条件不确定(ifelse判断),容易出错,特殊转义字符比如大于小于 。
注解方式:复杂sql不好用,搜集sql不方便,管理不方便,修改需重新编译
总结
本文讲述了Mybatis的两种映射方式,以及一些注意点,一些关系和区别。
实体属性名和数据库表字段名不一样的情况下,xml和注解分别是如何处理的。resultType和resultMap的区别。
-->很赞哦!(44138)
站长推荐
a、变更前的公司证件扫描件(代码证或者营业执照)及联系人身份证复印件、变更后的公司证件扫描件(代码证或者营业执照)及新的联系人身份证复印件;身份证复印件需本人签名,公司证件复印件需加盖公章。
时域音频分离模型登GitHub热榜,效果超传统频域方法
如果你打算在2020年学习Java,千万别错过这些书
1亿人点赞的晚会,如何做技术沉淀?
4、企业无形资产:通用网站已成为企业网络知识产权的重要组成部分,属于企业的无形资产,也有助于提升企业的品牌形象和技术领先形象。它是企业品牌资产不可或缺的一部分。
如你所愿?如果有一天,JavaScript彻底消失了……
TIOBE榜单发布:超越Python!C语言荣获 2019 年度最佳编程语言
2019年面向企业的10种优秀编程语言