注意要点
-
全局配置文件中,各个标签要按照如下顺序进行配置,因为mybatis加载配置文件的源码中是按照这个顺序进行解析的
<configuration> <!-- 配置顺序如下 properties settings typeAliases typeHandlers objectFactory plugins environments environment transactionManager dataSource mappers --> </configuration>
各个子标签说明如下
<properties>
一般将数据源的信息单独放在一个properties文件中,然后用这个标签引入,在下面environment标签中,就可以用${}占位符快速获取数据源的信息
<settings>
用来开启或关闭mybatis的一些特性,比如可以用<setting name="lazyLoadingEnabled" value="true"/>来开启延迟加载,可以用<settings name="cacheEnabled" value="true"/>来开启二级缓存
<typeAliases>
在mapper.xml中需要使用parameterType和resultType属性来配置SQL语句的输入参数类型和输出参数类型,类必须要写上全限定名,比如一个SQL的返回值映射为Student类,则resultType属性要写com.yogurt.po.Student,这太长了,所以可以用别名来简化书写,比如
<typeAliases> <typeAlias type="com.yogurt.po.Student" alias="student"/> </typeAliases>
之后就可以在resultType
上直接写student
,mybatis会根据别名配置自动找到对应的类。
当然,如果想要一次性给某个包下的所有类设置别名,可以用如下的方式
<typeAliases> <package name="com.yogurt.po"/> </typeAliases>
如此,指定包下的所有类,都会以简单类名的小写形式,作为它的别名
另外,对于基本的Java类型 -> 8大基本类型以及包装类,以及String类型,mybatis提供了默认的别名,别名为其简单类名的小写,比如原本需要写java.lang.String,其实可以简写为string
<typeHandlers>
用于处理Java类型和Jdbc类型之间的转换,mybatis有许多内置的TypeHandler,比如StringTypeHandler,会处理Java类型String和Jdbc类型CHAR和VARCHAR。这个标签用的不多
<objectFactory>
mybatis会根据resultType或resultMap的属性来将查询得到的结果封装成对应的Java类,它有一个默认的DefaultObjectFactory,用于创建对象实例,这个标签用的也不多
<plugins>
可以用来配置mybatis的插件,比如在开发中经常需要对查询结果进行分页,就需要用到pageHelper分页插件,这些插件就是通过这个标签进行配置的。在mybatis底层,运用了责任链模式+动态代理去实现插件的功能
<!-- PageHelper 分页插件 --> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <property name="helperDialect" value="mysql"/> </plugin> </plugins>
<environments>
用来配置数据源
<mappers>
用来配置mapper.xml映射文件,这些xml文件里都是SQL语句
mapper.xml的SQL语句中的占位符${}和#{}
一般会采用#{},#{}在mybatis中,最后会被解析为?,其实就是Jdbc的PreparedStatement中的?占位符,它有预编译的过程,会对输入参数进行类型解析(如果入参是String类型,设置参数时会自动加上引号),可以防止SQL注入,如果parameterType属性指定的入参类型是简单类型的话(简单类型指的是8种java原始类型再加一个String),#{}中的变量名可以任意,如果入参类型是pojo,比如是Student类
public class Student{ private String name; private Integer age; //setter/getter }
那么#{name}表示取入参对象Student中的name属性,#{age}表示取age属性,这个过程是通过反射来做的,这不同于${},${}取对象的属性使用的是OGNL(Object Graph Navigation Language)表达式
而${},一般会用在模糊查询的情景,比如SELECT * FROM student WHERE name like '%${name}%';
它的处理阶段在#{}之前,它不会做参数类型解析,而仅仅是做了字符串的拼接,若入参的Student对象的name属性为zhangsan,则上面那条SQL最终被解析为SELECT * FROM student WHERE name like '%zhangsan%';
而如果此时用的是SELECT * FROM student WHERE name like '%#{name}%'; 这条SQL最终就会变成
SELECT * FROM student WHERE name like '%'zhangsan'%'; 所以模糊查询只能用${},虽然普通的入参也可以用${},但由于${}不会做类型解析,就存在SQL注入的风险,比如
SELECT * FROM user WHERE name = '${name}' AND password = '${password}'
我可以让一个user对象的password属性为'OR '1' = '1,最终的SQL就变成了
SELECT * FROM user WHERE name = 'yogurt' AND password = ''OR '1' = '1',因为OR '1' = '1'恒成立,这样攻击者在不需要知道用户名和密码的情况下,也能够完成登录验证
另外,对于pojo的入参,${}中获取对象属性的语法和#{}几乎一样,但${}在mybatis底层是通过OGNL表达式语言进行处理的,这跟#{}的反射处理有所不同
对于简单类型(8种java原始类型再加一个String)的入参,${}中参数的名字必须是value,例子如下
<select id="fuzzyCount" parameterType="string" resultType="int"> SELECT count(1) FROM `user` WHERE name like '%${value}%' </select>
上面其实是比较原始的开发方式,我们需要编写dao类,针对mapper.xml中的每个SQL标签,做一次封装,SQL标签的id要以字符串的形式传递给SqlSession的相关方法,容易出错,非常不方便;为了简化开发,mybatis提供了mapper接口代理的开发方式,不需要再编写dao类,只需要编写一个mapper接口,一个mapper的接口和一个mapper.xml相对应,只需要调用SqlSession对象上的getMapper(),传入mapper接口的class信息,即可获得一个mapper代理对象,直接调用mapper接口中的方法,即相当于调用mapper.xml中的各个SQL标签,此时就不需要指定SQL标签的id字符串了,mapper接口中的一个方法,就对应了mapper.xml中的一个SQL标签
基于Mapper代理的示例
全局配置文件和mapper.xml文件是最基本的配置,仍然需要。不过,这次我们不编写dao类,直接创建一个mapper接口
package com.yogurt.mapper; import com.yogurt.po.Student; import java.util.List; public interface StudentMapper { List<Student> findAll(); int insert(Student student); int delete(Integer id); List<Student> findByName(String value); }
mapper.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.yogurt.mapper.StudentMapper"> <select id="findAll" resultType="com.yogurt.po.Student"> SELECT * FROM student; </select> <insert id="insert" parameterType="com.yogurt.po.Student"> INSERT INTO student (name,score,age,gender) VALUES (#{name},#{score},#{age},#{gender}); </insert> <delete id="delete" parameterType="int"> DELETE FROM student WHERE id = #{id}; </delete> <select id="findByName" parameterType="string" resultType="student"> SELECT * FROM student WHERE name like '%${value}%'; </select> </mapper>
mapper接口和mapper.xml之间需要遵循一定规则,才能成功的让mybatis将mapper接口和mapper.xml绑定起来
- mapper接口的全限定名,要和mapper.xml的namespace属性一致
- mapper接口中的方法名要和mapper.xml中的SQL标签的id一致
- mapper接口中的方法入参类型,要和mapper.xml中SQL语句的入参类型一致
- mapper接口中的方法出参类型,要和mapper.xml中SQL语句的返回值类型一致
测试代码如下
public class MapperProxyTest { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws IOException { InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); } @Test public void test() { SqlSession sqlSession = sqlSessionFactory.openSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> studentList = mapper.findAll(); studentList.forEach(System.out::println); } }
结果如下
这个mapper接口,mybatis会自动找到对应的mapper.xml,然后对mapper接口使用动态代理的方式生成一个代理类
标签:xml,mapper,类型,name,学习,mybatis,SQL,Mybatis,日志 From: https://www.cnblogs.com/yzx-sir/p/17220663.html