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]}<!--顯示頁碼的具體頁數 -->