MyBatis注解方式就是将SQL语句直接写在接口上。可以用在需求比较简单的系统,当SQL有变化时都需要重新编译代码,一般不用注解。
使用mapUnderscoreToCamelCase配置
MyBatis3.3.1版本开始,@Results注解增加了一个id属性,设置id属性后,就可以通过id属性引用同一个@Results配置了。
使用resultMap方式
@Insert注解
@update注解和@Delete注解
Provider注解:
1.Procider的注解中提供了两个必填属性type和method。
2.type配置的是一个包含method属性指定的类,这个类必须有空的构造方法,这个方法的值就是要执行的SQL语句,并且method属性指定的方法的返回值必须是String类型。拼接SQL语句使用new SQL(){...}方法
现在MyBatis采用了OGNL(Object-Graph Naviigation Language)表达式语言消除了许多其他标签,以下是MyBatis的动态SQL在XML中支持的几种标签:
1.if标签通常用于WHERE语句中,通过判断参数值来决定是否使用某个查询条件,它也经常用于UPDATE语句中判断是否更新某一个字段,还可以在INSERT语句中用来判断是否插入某个字段的值。
2.在WHERE条件中使用if
if标签有一个必填的属性test,test的属性值是一个符合OGNL要求的判断表达式,表达式的结果可以是true或false,除此之外所有的非0值都为true,只有0为false。
3.对字符串的判断和Java中的判断类似,首先需要判断字段是否为null,然后再去判断是否为空(在OGNL表达式中,这两个判断的顺序不会影响判断的结果,也不会有空指针异常)
在UPDATE更新列中使用if
在数据库表中插入数据的时候,如果某一列的参数不为空,就使用传入的值,如果传入参数为空,就使用数据库中的默认值(通常是空),而不使用传入的空值。使用if就可以实现这种动态传入的功能。
要实现if...else这样的逻辑就需要用到choose when otherwise标签。choose元素中包含when和otherwise两个标签,一个choose中至少有一个when,有0个或者1个也是唯一的,所有的用户名都不可以重复。
如果该标签包含的元素中有返回值,就插入一个where;如果where后面的字符串是以AND和OR开头的,就将它们剔除。
trim在底层就是通过TrimSqlNode实现的
where标签对应trim的实现如下
这里的AND和OR后面的空格不能省略,为了避免匹配到andes,orders等单词。
实际的prefixeOverrides包含“ADN”、“OR”、“AND\n”、“OR\n”、“OR\r”、“AND\t”、“OR\t”,不仅仅是上面提到的带空格的前缀。
1.只有一个数组参数或集合参数
2.有多个参数
当有多个参数的时候,要使用@Param注解给每个参数指定一个名字,否则在SQL中使用参数时就会不方便,因此collection设置为@Param注解指定的名字即可。
3.参数时Map类型
使用Map和使用@Param注解方式类似,将collection指定为对应Map中的key即可。
如果要循环所传入的Map,推荐使用@Param注解指定名字,此时可将collection设置为指定的名字,如果不想指定名字,就使用默认值_parameter.
4.参数时一个对象
这种情况下指定为对象的属性名即可,当使用对象内多层嵌套的对象时,使用属性,属性(集合和数组可以使用下标取值)的方式可以指定深层的属性值。
批量插入SQL-92新增的特性,批量插入的语法如下。
INSERT INTO tablename (column-a,[column-b,...])
VALUES('value-1a',['value-1b',...]),
('value-2a',['value-2b',...]),
...
从待处理部分可以看出,后面时一个值的循环,因此可以通过foreach实现循环插入。
当参数是Map类型的时候,foreach标签的index属性值对应的不是索引值,而是Map中的key,利用这个Key可以实现动态UPDATE。
1.bind标签可以使用OGNL表达式创建一个变量并将其绑定到上下文。
2.使用concat函数连接字符串,在MYSQL中,这个函数支持多个参数,如果更换数据库,有些SQL语句可能就需要重写。针对这种情况,可以使用bind标签来避免由于更换数据库带来的一些麻烦。
3.bind标签的两个属性都是必选项,name为绑定到上下文的变量名,value为OGNL表达式。创建一个bind标签的变量后,就可以在下面直接使用,使用bind拼接字符串不仅可以避免因更换数据库而修改SQL,也能预防SQL注入。
MyBatis提供的databaseIdProvider数据库厂商标识配置基于映射语句中的databaseId属性的。MyBatis会加载不带databaseId
属性和带有匹配当前数据库databaseId属性的所有语句。
如果同时找到带有databaseId和不带databaseId的相同语句,则后者会被舍弃。
mybatis-config.xml文件加入databaseIdProvider配置即可
这里的DB_VENDOR会通过DatabaseMetData#getDatabaseProductName()返回的字符串进行设置。
1.在有property配置时,databaseId将被设置为第一个能匹配数据库产品名称的属性键对应的值。
2.如果没有匹配的属性则会被设置为null.
3.数据库产品名一般由选择的当前数据库的JDBC驱动所决定,只要找到对应数据库DatabaseMetaData接口的实现类,一般在getDatabaseProductName()方法中就可以直接找到该值。任何情况下都可以通过调用DatabaseMetaData#getDatabaseProductName()方法获取具体的值。
4.增加以上配置外,映射文件也要变化的,关键在于以下几个映射文件的标签中含有的databaseId属性:
当基于不同数据库运行时,MyBatis会根据配置扎到合适的SQL去执行。
在MyBatis的动态SQL和${}形式的参数中都用到了OGNL表达式。
1.e1 or e2
2.e1 and e2
3.e1 == e2 或 e1 eq e2
4.e1 != e2 或 e1 neq e2
5.e1 lt e2:小于
6.e1 lte e2:小于等于,其他表示为gt(大于)、gte(大于等于)
7.e1 + e2、e1 * e2、e1/e2、e1 - e2、e1%e2
8.!e 或 not e:非,取反
9.e.method(args):调用对象方法
10.e.property:对象属性值
11.e1[e2]:按索引取值(List、数组和Map)
12. @class@method(args): 调用类的静态方法
13. @class@field: 调用类的静态字段值
1.Mybatis代码生成器(MyBatis Generator)MBG代码包含了数据表对应的实体类、Mapper接口类、MapperXML文件和Example对象等。
首先按照MBG的要求添加XML的文件头mybatis-generator-config_1_0.dtd用于定义配置文件中所有标签和属性的用法及限制,在文件头之后,需要写上XML文件的根节点generatorConfiguration.generatorConfiguration标签下的3个子级标签,分别时properties、classPathEntry和context。
2.在配置这3个标签的时候,必须注意它们的顺序,要和这里列举的顺序一致,在后面列举其他标签的时候,也必须严格按照列举
这些标签的顺序进行配置。
1.defaultModelType:这个属性很重要,定义了MBG如何生成实体类。该属性有以下可选值
2.conditionnal:默认值,和下面的hierarchical类似,如果一个表的主键只有一个字段,那么不会为该字段生成单独的实体类,而是会将该字段合并到基本实体类中。
3.flat:该模型只为每张表生成一个实体类。这个实体类包含表中的所有字段。
4.hierarchical:如果表有主键,那么该模型会产生一个单独的主键实体类,如果还有BLOB字段,则会为表生成一个包含所有BLOB字段的单独的实体类,然后为所有其他字段另外生成一个单独的实体类。MBG会在所有生成的实体类之间维护一个继承关系。
5.targetRuntime:此属性用于指定生成的代码的运行时环境,支持以下可选值。
6.MyBatis3:默认值
7.MyBatis3Simple:这种情况不会生成与Example相关的方法。
8.introspectedColumnImpl:该参数可以指定扩展org.mybatis.generator.api.Introspected Column类的实体类。
一般情况下使用如下配置即可。
如果不希望生成和Example查询有关的内容,则可以按照如下方法进行配置。
MBG配置中的其他几个标签基本上都是context的子标签,这些子标签(有严格的配置顺序,后面括号中的内容为这些标签可以配置的个数)包含以下几个。
property(0或多个)
plugin(0个或多个)
commentGenerator(0个或1个)
jdbcConnection(1个)
javaTypeResolver(0个或1个)
javaModelGenerator(1个)
sqlMapGenerator(0个或1个)
javaClientGenerator(0个或1个)
table(1个或多个)
在开始介绍property标签前,先来了解一下数据库中的分隔符。