1、动态sql语句html
bean部分的User类代码:java
public class User { private int id; private String name; private int age;//若是在if判断中用null,则把int改为Integer private String sex; private List<Integer> ids; }
dao部分的接口UserDao代码:mysql
public interface UserDao { /** * 根据id查询 * @param id * @return */ public User selectByWhere1(User user); public User selectByWhere2(User user); public User selectByWhere3(User user); /** * 添加 * @param user */ public void addUser(User user); /** * 删除用户 * @param id */ public void deleteByIds(User ids); public void delete(@Param("ids") List<Integer> ids); //调用其余的类型要先设置key,Mybatis默认为map public void deleteByIds2(User ids); /** * 更新用户 * @param user */ public void updateUser(User user); }
如下为mapper.xml部分:git
1.if语句github
<!-- 根据name和sex来查询数据。若是name为空,那么将只根据sex来查询;反之只根据name来查询
缺点:若是第二个条件知足,第一个条件不知足,那么就会致使sql语句出错
where 1=1 防止where后面什么也没有会报错
-->sql
<select id="selectByWhere1" parameterType="int" resultType="com.zhiyou100.xz.bean.User"> select * from users <if test="name!=null"> where name=#{name} </if> <if test="sex!=null and sex!=''"> and sex=#{sex} </if> </select>
2.if+where 语句数据库
<!-- 解决:若是第二个条件知足,第一个条件不知足,那么就会致使sql语句出错
if+where:若是第一个条件知足,则用where,并去掉where后的and
-->apache
<select id="selectByWhere2" resultType="com.zhiyou100.xz.bean.User"> select * from users <where> <if test="name!=null"> and name=#{name} </if> <if test="sex!=null and sex!=''"> and sex=#{sex} </if> </where> </select>
3. if+set 语句api
<!-- if+set:若是传来的字段为null,那么保留原来的内容 --> <update id="updateUser" parameterType="com.zhiyou100.xz.bean.User"> update users <set> <if test="name!=null"> name=#{name}, </if> <if test="sex!=null and sex!=''"> sex=#{sex}, </if> <if test="age>0"> age=#{age} </if> </set> where id=#{id} </update>
4. choose(when,otherwise) 语句session
<!-- choose+where+otherwise --> <select id="selectByWhere3" resultType="com.zhiyou100.xz.bean.User"> select * from users <where> <choose> <when test="name!=null and name!=''"> name like concat('%',#{name},'%') </when> <when test="sex!=null and sex!=''"> sex=#{sex} </when> <otherwise> age>=#{age} </otherwise> </choose> </where> </select>
5. trim 语句
<!-- trim --> <select id="selectByWhere2" resultType="com.zhiyou100.xz.bean.User"> select * from users <trim prefix="where" prefixOverrides="and / or"> <if test="name!=null"> and name=#{name} </if> <if test="sex!=null and sex!=''"> and sex=#{sex} </if> </trim> </select>
<!-- trim --> <update id="updateUser" parameterType="com.zhiyou100.xz.bean.User"> update users <!-- prefix:把trim中返回的字符串前添加一个set prefixOverrides:覆盖trim中返回的字符串的前缀为and | or suffix:把trim中返回的字符串后添加一个指定字符串 suffixOverrides:覆盖trim中返回的字符串的前缀 --> <trim prefix="set" suffixOverrides=","> <if test="name!=null"> name=#{name}, </if> <if test="sex!=null and sex!=''"> sex=#{sex}, </if> <if test="age>0"> age=#{age} </if> </trim> where id=#{id} </update>
6. SQL 片断
<!-- sql片断 --> <sql id="usercolumns"> id,name,age,sex </sql> <select id="selectByWhere1" parameterType="int" resultType="com.zhiyou100.xz.bean.User"> select <!-- 引用相应的sql片断 --> <include refid="usercolumns" /> from users <if test="name!=null"> where name=#{name} </if> <if test="sex!=null and sex!=''"> and sex=#{sex} </if> </select>
7. foreach 语句
<!-- delete from users where id in(?,?,?) --> <delete id="deleteByIds"> delete from users where id in <!-- collection:表示要遍历的集合名称 open:以(做为开始 close:以)做为结束 separator:每一个元素之间使用,分割 item:每次遍历的值赋值给的变量名 --> <foreach collection="ids" open="(" close=")" separator="," item="id"> #{id} </foreach> </delete> <!-- delete from users where id=1 or id=4 or id=6 --> <delete id="delete"> delete from users <!-- collection:表示要遍历的集合名称 open:以(做为开始 close:以)做为结束 separator:每一个元素之间使用,分割 item:每次遍历的值赋值给的变量名 这里最好不要在foreach标签中用open="where " 由于当id等于0时,作全表删除时会报错 --> <where> <foreach collection="ids" separator="or" item="id"> id=#{id} </foreach> </where> </delete>
8. 总结
其实动态 sql 语句的编写每每就是一个拼接的问题,为了保证拼接准确,咱们最好首先要写原生的 sql 语句出来,而后在经过 mybatis 动态sql 对照着改,防止出错。
2、逆向工程
经过前面的学习,在实际开发中,咱们基本上能对mybatis应用自如了,可是咱们发现了一个问题,全部操做都是围绕着po类,xxxMapper.xml文件,xxxMapper接口等文件来进行的。若是实际开发中数据库的表特别多,那么咱们须要手动去写每一张表的po类,xxxMapper.xml,xxxMapper.java文件,这显然须要花费巨大的精力,并且可能因为表字段太多,写错了而不知道也是可能的。
因此咱们在实际开发中,通常使用逆向工程方式来自动生成所需的文件,如dao,bean,xml映射文件 。
http://www.mybatis.org/generator/index.html
1.新建一个工程并导入jar包
注意:使用逆向工程时,最好新建一个工程,若是你在原来的工程中使用,那也能够,可是有必定的风险,由于mybatis是根据配置文件中配置的路径来生成的文件的,若是你工程中有相同名字的文件,那么就会被新生成的文件所覆盖。因此实际开发中,咱们通常新建一个工程,将生成的文件复制到本身的所需的工程中。
2.建立generator.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- mysql驱动jar所在的位置 --> <classPathEntry location="D:\\mysql\\mysql-connector-java-5.1.47.jar" /> <!-- 数据源的信息 --> <context id="DB2Tables" targetRuntime="MyBatis3"> <!-- 禁止全部注释 --> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="root"> </jdbcConnection> <javaTypeResolver > <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- 生产的实体类所在的位置 --> <javaModelGenerator targetPackage="com.zhiyou100.xz.bean" targetProject="./src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- 生成的映射文件所在的位置 --> <sqlMapGenerator targetPackage="com.zhiyou100.xz.mapper" targetProject="./resources"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- 生产的dao文件所在位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.zhiyou100.xz.dao" targetProject="./src"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 某张表与实体类的对应关系 schema:该表所在的数据库 tableName:表名 domainObjectName:实体类名
当须要多张表创建实体类时要创建多个table标签 --> <table schema="mybatis" tableName="users" domainObjectName="Users" enableCountByExample="false" enableSelectByExample="false" enableUpdateByExample="false" enableDeleteByExample="false">
<!--以Example结尾的属性全为false,是为了减小生成复杂的方法 --> <property name="useActualColumnNames" value="true"/> <generatedKey column="ID" sqlStatement="DB2" identity="true" /> <columnOverride column="DATE_FIELD" property="startDate" /> <ignoreColumn column="FRED" /> <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" /> </table> </context> </generatorConfiguration>
注意:
一、链接数据库的配置,包括数据名称,数据库用户名密码等配置
二、指定要生成代码的包名,包括实体类po的包名,mapper的包名等
三、指定数据库中哪些表须要生成文件
3.运行主程序生成代码
package com.zhiyou100.xz.test; import java.io.File; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.internal.DefaultShellCallback; public class Test { public static void main(String[] args) throws Exception{ List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("generator.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } }
3、分页查询助手pagehelper
1.导入jar包
https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md
2.在mybatis工程下的conf.xml中配置PageHelper的拦截器插件
<!-- plugins在配置文件中的位置必须符合要求,不然会报错,顺序以下: properties?, settings?, typeAliases?, typeHandlers?, objectFactory?,objectWrapperFactory?, plugins?, environments?, databaseIdProvider?, mappers? --> <plugins> <!-- com.github.pagehelper为PageHelper类所在包名 --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 使用下面的方式配置参数,后面会有全部的参数介绍 --> <property name="param1" value="value1"/> </plugin> </plugins>
3.先在UsersMapper.xml中写出查询全部的sql语句
<resultMap id="BaseResultMap" type="com.zhiyou100.xz.bean.Users"> <id column="id" jdbcType="INTEGER" property="id" /> <result column="NAME" jdbcType="VARCHAR" property="NAME" /> <result column="age" jdbcType="INTEGER" property="age" /> <result column="sex" jdbcType="VARCHAR" property="sex" /> </resultMap> <sql id="Base_Column_List"> id, NAME, age, sex </sql> <!-- 查询全部 --> <select id="selectAll" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from users </select>
4.在接口UsersMapper中写 出查询全部的方法
package com.zhiyou100.xz.dao; import java.util.List; import com.zhiyou100.xz.bean.Users; public interface UsersMapper { //查询全部用户 List<Users> selectAll(); }
5.测试运行,并在其中使用PageHelper类设置起始页与每页显示的条数和用pageInfo进行查询结果的封装。
package com.test; import java.io.Reader; import java.util.ArrayList; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.zhiyou100.xz.bean.Users; import com.zhiyou100.xz.dao.UsersMapper; class TestMybatis { static SqlSession session=null; final String str="com.zhiyou100.xz.mapper.UserMapper"; static UsersMapper usersMapper; @BeforeAll static void setUpBeforeClass() throws Exception { //解析配置文件conf.xml Reader reader=Resources.getResourceAsReader("conf.xml"); //获取SessionFactory对象 SqlSessionFactory sessionFactory=new SqlSessionFactoryBuilder().build(reader); //获取Session对象,表示jdbc中connection,操做数据库的 session=sessionFactory.openSession(); //获得接口的实现类 usersMapper=session.getMapper(UsersMapper.class);//至关于建立一个Dao对象 } @Test void testSelectByPage() {
// 1.使用PageHelper类设置起始页和每页显示的条数
int pageNum = 3;// 当前的页码 从网页中能够获取
int pageSize = 2;// pageSize:自定义
PageHelper.startPage(pageNum, pageSize);
// 2.调用查询全部的方法
List<Users> list = usersMapper.selectAll();
System.out.println(list);
// 3.把查询的結果封裝到pageInfo对象中
PageInfo<Users> pageInfo = new PageInfo<>(list,3);
System.out.println(pageInfo);
//pageInfo.setNavigatePages(2);//setNavigatePages 设置每页显示的页码个数,这里这个属性没起做用
System.out.println("总页码:"+pageInfo.getPages());
System.out.println("当前页:"+pageInfo.getPageNum());
System.out.println("上一页:"+pageInfo.getPrePage());
int[] pages=pageInfo.getNavigatepageNums();//getNavigatepageNums显示页码的具体页数
for(int p:pages) {
System.out.print(p+"\t");
}
System.out.println("下一页:"+pageInfo.getNextPage());
List<Users> users=pageInfo.getList();
for(Users users2:users) {
System.out.println(users2);
}
} @AfterAll static void tearDownAfterClass() throws Exception { session.commit();//提交数据 事物管理:要么都执行,要么都不执行 } }
6.对pageInfo对象中各个属性的解释
PageInfo{pageNum=3,<!--当前页码 --> pageSize=2,<!--每页显示的条数 --> size=2,<!--该页的实际条数 --> startRow=5,<!--从第几条开始 --> endRow=6, total=8,<!--到第几条结束 --> pages=4,<!-- 总共的页数--> list=Page{count=true, pageNum=3, pageSize=2, startRow=4, endRow=6, total=8, pages=4, reasonable=false, pageSizeZero=false} [Users [id=5, NAME=孔妖精, age=18, sex=小妖精], Users [id=10, NAME=孔妖精, age=20, sex=骚妖精]],<!--当前页的数据 --> prePage=2,<!--上一页 --> nextPage=4,<!--下一页 --> isFirstPage=false, <!--是否为第一页 --> isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=8,<!--每页显示的页码个数 --> navigateFirstPage=1, navigateLastPage=4, navigatepageNums=[1, 2, 3, 4]}<!--显示页码的具体页数 -->