本文转载自微信公众号《Java后端技术全栈》,作者田伟昌。转载本文请联系Java后端技术全栈公众号。MyBatis提供了XML配置和注解配置两种方式。今天,我们就来说说这两个方法是如何实现的。MyBatis真正强大的地方在于它的语句映射,这也是它神奇的地方。由于它的强大,映射器的XML文件相对简单。如果将它与具有相同功能的JDBC代码进行比较,您会立即看到代码节省了近95%。MyBatis致力于降低使用成本,让用户更专注于SQL代码。来自官网。Mybatis映射九个顶级元素:mapper:映射文件的根节点,只有一个属性命名空间(namespace),其作用如下:用于区分不同的mapper,全局唯一。绑定DAO接口就是面向接口的编程。绑定接口时,不需要编写接口的实现类。你会通过接口全限定名找到对应的mapper配置来执行SQL语句。因此,命名空间的名称必须写成接口的全限定名。缓存:为给定的命名空间配置缓存。cache-ref:从其他命名空间引用缓存配置。resultMap:用于描述数据库结果集与对象的对应关系。sql:一个可重用的SQL块,也可以被其他语句引用。通常存放一些常用的SQL。insert:映射插入语句。更新:更新映射语句。delete:删除映射语句。select:映射查询语句。xml方式标签对应的九个顶级映射元素:select详细解释可以看,后面的选项还蛮多的。以下是官方网站上对每一项的解释。选择用例select*fromm_userwhereid=#{id}id在这个Mapper中必须是唯一的,可以用来引用这个语句。这个id只能和XxxMapper.java中的方法对应,必须是一一对应的。返回类型:用户类型,resultType:查询语句返回的结果类型的完全限定名或别名。别名的使用方式与parameterType相同。参数:整数,表示查询语句传入的参数的类型和完全限定名或别名。支持基本和复杂数据类型。#{parametername}:告诉MyBatis生成PreparedStatement参数。与JDBC相比,参数标记为'?'。别名和参数映射类型如下:在返回类型中使用别名,注意:如果是我们的实体类,那么resultType不能使用别名,只有resultMap可以使用别名。select*fromm_userwhereid=#{id}但是如果使用上面的映射表,也可以直接使用别名。数据库里有两条数据:UserMapper.xmlselectcount(1)fromm_userUserMapper.javaimportcom.tian.mybatis.entity.User;publicinterfaceUserMapper{intcountUser();}测试类:publicclassMybatisApplication{publicstaticfinalStringURL="jdbc:mysql://localhost.com:3306/mblog?useUnicode=true";publicstaticfinalStringUSER="root";publicstaticfinalStringPASSWORD="123456";publicstaticvoidmain(String[]args){Stringresource="mybatis-config.xml";InputStreaminputStream=null;SqlSessionsqlSession=null;try{inputStream=Resources.getResourceAsStream(resource);//工厂模型SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(inputStream);//获取sql操作sessionsqlSession=sqlSessionFactory.openSession();//构造对象(这里比较特殊,后面会分享这里构造对象的方法)UserMapperuserMapper=sqlSession.getMapper(UserMapper.class);//查询统计System.out.println(userMapper.countUser());}catch(Exceptione){e.printStackTrace();}finally{try{inputStream.close();}catch(IOExceptione){e.printStackTrace();}sqlSession.close();}}}输出:2当数据库表中的字段名与我们实体中的字段名不一致时,如何处理?在实际开发中,这种常见是不可避免的。我们可以使用下面的方法来解决。实体类UserpublicclassUser{privateIntegerid;privateStringuserName;privateIntegerage;//setgettoString方法这里就不贴了}UserMapper.xml文件内容:select*fromm_userwhereid=#{id}type:对应我们的实体类,全路径名。id:可以理解为别名。id:唯一标识,这个id值用于select元素的resultMap属性的引用。column:对应我们数据库表中的字段名。property:对应我们实体类的属性,比如:User中的属性userName应该对应数据库表m_user中的name。result:标识一些简单的属性,其中column属性代表数据库的字段名,property代表查询到的字段名,映射到实体类的某个属性。继续使用我们之前的测试类进行测试:UserMapperuserMapper=sqlSession.getMapper(UserMapper.class);System.out.println(userMapper.selectUserById(1));输出:User{id=1,userName='tian',age=22}注:这里省略了实体类的getset和toString()方法,希望大家可以使用,使用快捷键获取它很容易完成。上面提到了resultType和resultMap,那么它们有什么区别呢?resultType和resultMap有什么区别?resultType:直接表示返回类型,包括基本数据类型和复杂数据类型。resultMap:对外部resultMap定义的引用。对应的外部resultMap的id表示结果映射到哪个resultMap。一般用于字段名和属性名不一致,或者需要复杂联合查询自由控制映射结果的情况。两者的关系查询的时候,查询的每个字段都会放在一个Map中。当query元素返回一个resultType的属性时,会取出key-value对赋值给指定的属性。其实MyBatis中每个查询映射的返回类型都是resultMap,但是当我们使用resultType时,会自动将对应的值赋值给指定的对象属性。在使用resultMap时,由于map并不能很好的表示字段,我们会进一步将其转化为对应的实体对象。resultMap主要用于复杂的联合查询。resultMap的自动映射级别:默认级别为PARTIAL,也可以在设置中更改该值。注意:resultType和resultMap本质上是一样的,都是Map数据结构,但是两者不能同时存在。从这里可以知道增删改insert的情况。添加insert时没有返回值类型需要我们指定。默认返回int类型。INSERTINTOM_user(`name`,age)VALUES(#{userName},#{age})对应ininsert中的方法映射器(用户用户);其他的update与delete类似,这里就不再一一演示了。注解方式9个顶层映射元素对应注解:其他注解与9个注解结合使用。select注解删除本地的UserMapper.xml,然后更改mybatis-config.xml,注释掉其中的UserMapper.xml。添加UserMapper.java添加注解publicinterfaceUserMapper{@Select("select*fromm_userwhereid=#{id}")UserselectUserById(Integerid);}再次测试Useruser=sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById",1);System.out.println(用户);Output:User{id=1,userName='null',age=22}从输出内容看userName为null,也是与数据库表中的字段名不一致导致的,那么如何处理呢?这样,再添加一个注解:publicinterfaceUserMapper{@Select("select*fromm_userwhereid=#{id}")@Results(@Result(column="name",property="userName"))UserselectUserById(Integerid);}输出:User{id=1,userName='tian',age=22}这个是使用注解有时候,处理实体属性名和数据库表字段名不同的方式。插入、更新和删除也可以使用注释来完成。@Insert、@Update、@Delete与相应的SQL语句匹配。注解和xml可以共存吗?updatem_user`name`=#{userName},gender=#{gender},age=#{age},age=#{age},age=#{age},whereid=#{id}同时给UserMapper.java中的方法添加注解@Update("updatem_userset`name`=#{userName},gender=#{gender},age=#{age}whereid=#{id}")intupdateAuthorIfNecessary(用户用户);再次返回中子星时,异常:nestedexceptionisjava.lang.IllegalArgumentException:MappedStatementscollectionalreadycontainsvalueforcom.tian.mybatis.mapper.UserMapper.updateAuthorIfNecessary.pleasecheckfile[D:\workspace\my_code\mybatis\target\classes\mapper\UserMapper.xml]andcom/tian/mybatis/mapper/UserMapper.java(bestguess)大致意思是已经存在,即xml和注解不能同时使用。选择两者之一。XML可以和注解结合使用,但是必须保证XML和注解不能同时存在于同一个方法中。推荐简单的sql处理使用注解,复杂的sql使用xml。但是实际的工作取决于这个在你等待的项目中是否标准化。项目中无外乎三种:1.都必须使用xml方式。2.都必须使用注解。3.XML和注解可以同时使用。高级映射关联映射到JavaBean的一个复杂的“数据类型”属性,只处理一对一的关联。关联属性节点:property:映射数据库列的实体对象的属性名。javaType:完整的java类名和限定名。属性映射到的属性类型。子元素id:一般为映射主键,可以提高性能。result:column:映射数据库的字段名。property:映射数据列对应的实体对象属性。集合被映射到JavaBean的一个复杂的“数据类型”属性,它是一个集合列表,处理一对多的关联。ofType:完整的Java类名和限定名.属性映射到的属性类型。其余与association基本相同。关联和集合都具有延迟加载功能。懒加载:先从单表查询,需要的时候再去查关联表,大大提高了数据库的性能,因为相对来说,单表查询比多表查询快。xml和注解的关系上面两个方法的实现我们已经讲过了。我们来对比一下这两个方法的关系:xml方法必须有一个XxxMapper.xml与之对应,方法名对应xml中的id,方法输入参数和方法输出参数必须匹配,很容易造成问题。我们在开发的时候,有的可以使用代码生成器来生成,但是有的必须自己写,有的公司还需要手写,所以这里需要注意一下。注解方法不需要XxxMapper.xml文件,只需要在对应的XxxMapper.java中的方法上加上注解即可,不过这里有坑。毕竟把sql放在我们的java代码里面。xml方式的优缺点:添加了xml文件,修改麻烦,条件不确定(ifelse判断),容易出错,大于小于小于等特殊转义字符。注释方法:复杂的sql不好用,不方便收集sql,不方便管理,修改需要重新编译总结本文介绍了Mybatis的两种映射方式,以及一些注意点,一些关系和区别。当实体属性名与数据库表字段名不同时,分别如何处理xml和注解。resultType和resultMap的区别。