MyBatis的總結(上)

一:走進MyBatis

框架:

    1:是一系列jar包,其本質是對JDK功能的拓展.

    2:框架是一組程序的組合,包含了一系列的最佳實踐,作用是解決某一個領域的問題.
WEB開發中的最佳實踐:根據職責的縱向劃分:控制層 業務層  持久層

    控制層:WEB/MVC: 負責處理頁面交互的相關操作(Struts2/Spring MVC)

    業務層:service: 負責複雜的業務邏輯計算和判斷(Spring)

    持久層:dao:     負責將業務邏輯數據進行持久化存儲(MyBatis/Hibernate)

    ![最佳實踐圖](https://img-blog.csdn.net/20180325191939870?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
ORM框架:

        遵循ORM思想實現的技術,解決的是持久層的問題(和數據庫做CRUD):

一個良好的持久層應該保證:

        當持久層的實現技術改變的時候,不會影響上一層的代碼(service).

    ![ORM思想](https://img-blog.csdn.net/20180325192600523?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
MyBatis:

        MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎

所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生信息,

將接口和 Java 的 POJOs(PlainOld Java Objects,普通的 Java對象)映射成數據庫中的記錄。

        https://mybatis.github.io/mybatis-3/zh/index.html 手冊裏面足夠學習了

二:基礎操作:

MyBatis依賴jar包:  在github下載裏面有好多好的項目源碼 多動手敲代碼

    1):MySQL驅動包:mysql-connector-java-5.1*jar

    2):核心包:mybatis-3.54.jar

    3):其他依賴.lib目錄中所有的jar(有需要再拷貝)

      mysql-connector-java-5.1.40.jar

    ![MyBatis的配置文件AND映射文件](https://img-blog.csdn.net/2018032519482747?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

    ![MyBatis-Config.xml](https://img-blog.csdn.net/2018032519520899?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
日誌文件的輸出:

    先拷貝jar包:

        slf4j-api-1.7.21.jar

        slf4j-log4j12-1.7.21.jar

        並配合log4j-1.2.17.jar一起使用

    log4j.properties文件內容:

        #設置全局的日誌配置:輸出Error級別,輸出到控制檯  日誌的級別:ERROR>WARN>INFO>DEBUG>TRACE級別越低,輸出的信息越詳細
        log4j.rootLogger=ERROR, stdout
        #設置自定義的日誌級別  每次記得修改包名
        log4j.logger.cn.wolfcode.mybatis.hello=TRACE
        log4j.appender.stdout=org.apache.log4j.ConsoleAppender
        log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
        log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
OGNL表達式:

        ![OGNL表達式](https://img-blog.csdn.net/20180325201451932?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
resultMap:

    主要解決表的列名跟屬性名稱不匹配的問題:

    ![resultMap](https://img-blog.csdn.net/20180325202006482?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
Mapper接口:

    Mapper接口的原理:動態代理:Spring的時候重點來講解

    ![Mapper組件](https://img-blog.csdn.net/20180325202550225?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
參數處理:

    //方式一:把多個參數封裝成一個JavaBean
    Client login1(LoginVO vo);

    //方式二:使用Map對象來封裝多個參數
    Client login2(Map<String, Object> paramMap);

    //方式三:使用Param註解,原理是方式二
    Client login3(@Param("username")String username,@Param("password")String password);

    List<Client> login4(@Param("orderby")String orderby);
    <select id="login1" parameterType="LoginVO" resultType="client">
        SELECT id,username,password FROM client Where username = #{username}
        AND password = #{password}
    </select>

    <select id="login2" parameterType="map" resultType="client">
        SELECT id,username,password FROM client Where username = #{username1}
        AND password = #{password1}
    </select>

    <select id="login3" resultType="client">
        SELECT id,username,password FROM client Where username = #{username}
        AND password = #{password}
    </select>

    <select id="login4" resultType="client">
        SELECT id,username,password FROM client
        ORDER BY ${orderby}
    </select>
    @Test
    public void testLogin1() throws Exception {
        LoginVO vo = new LoginVO("will","1111");
        SqlSession session = MyBatisUtil.getSession();
        ClientMapper clientMapper = session.getMapper(ClientMapper.class);
        Client client = clientMapper.login1(vo);
        session.close();
        System.out.println(client);
    }

    @Test
    public void testLogin2() throws Exception {
        Map<String,Object> paramMap = new HashMap<String,Object>(){
            {
                this.put("username1", "will");
                this.put("password1", 1111);
            }
        };
        SqlSession session = MyBatisUtil.getSession();
        ClientMapper clientMapper = session.getMapper(ClientMapper.class);
        Client clietn = clientMapper.login2(paramMap);
        session.close();
        System.out.println(clietn);
    }

    @Test
    public void testLogin3() throws Exception {
        SqlSession session = MyBatisUtil.getSession();
        ClientMapper clientMapper = session.getMapper(ClientMapper.class);
        Client clietn = clientMapper.login3("will","1111");
        session.close();
        System.out.println(clietn);
    }

    @Test
    public void testLogin4() throws Exception {
        SqlSession session = MyBatisUtil.getSession();
        ClientMapper clientMapper = session.getMapper(ClientMapper.class);
        List<Client> clietn = clientMapper.login4("id desc");
        session.close();
        for (Client c : clietn) {
            System.out.println(c);
        }
    }
    ![參數處理# &](https://img-blog.csdn.net/20180325203955827?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
MyBatipse插件:

        MyBatipseEclipse的一個插件,提供了內容提示和MyBatis的配置文件驗證功能!

三:註解開發

開發和配置MyBatis框架:

        方式一:使用XML配置,把SQL和映射寫在XML文件中.   推薦!

        方式二:使用註解配置,把SQL和映射寫在JAVA代碼中(Mapper接口).
public interface UserMapper {

    @Insert("insert into t_user value (#{id},#{name},#{salary})")
    @Options(useGeneratedKeys=true,keyProperty="id")
    void save(User u);

    @Update("UPDATE t_user set name = #{name}, salary = #{salary} where id = #{id}")
    void update(User u);

    @Delete("DELETE FROM t_user WHERE id = #{id}")
    void delete(Long id);

    @Select("SELECT * FROM t_user WHERE ID = #{id}")
    @Results(id="BaseResultMap",value={
            @Result(column="id",property="id"),
            @Result(column="name",property="name"),
            @Result(column="salary",property="salary")
    })
    User get(Long id);

    @Select("SELECT * FROM t_user")
    @ResultMap("BaseResultMap")
    List<User> listAll();
}
    既然修改了mapper文件,那麼

    mybatis-config.xml文件中修改爲<mapper> <mappec class=""/> </mapper>

四:動態SQL

choose:選擇,跟if  else 一個意思
    <choose>
        <when test="deptId > 0"> AND deptId = #{deptId}</when>
        <otherwise>AND deptId IS NOT NULL</otherwise>
    </choose>
Where:若果條件以AND或者OR開頭,就應該替換爲WHERE
set:如果中間以有值就輸入,最後一個去掉逗號,
    <set>
        <if test="name!=null">
            name = #{name},
        </if>
        <if test="password != null">
        password = #{password},
        </if>
    </set>
trim:可以替代where 跟set 一般不用

    ![trim的作用](https://img-blog.csdn.net/20180325213152704?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MDE2MTcwOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
mapper文件:

public interface EmployeeMapper {
    List<Employee> query(
            @Param("minSalary")BigDecimal minSalary,
            @Param("maxSalary")BigDecimal maxSalary,
            @Param("deptId") Long deptId
            );

    void batchDelete(@Param("ids") List<Long> ids);

    void batchSave(@Param("emps") List<Employee> emps);
}
        <!-- 
        foreach元素:
        collection屬性:表示對哪一個集合或數組做迭代
                        如果參數是數組類型,此時Map的可以爲array
                        如果參數是List類型,此時Map的key爲list
                        我們可以在參數上使用Param註解,規定死Map中key是什麼.@Param("ids")
                        open屬性:在迭代集合之前,拼接什麼符號.
                        close屬性:在迭代集合之後,拼接什麼符號.
                        separator屬性:在迭代元素時,每一個元素之間用什麼符號分割開來.    
                        item屬性:被迭代的每一個元素的變量
                        index屬性:迭代的索引   
         -->
    <delete id="batchDelete">
        DELETE employee where id in
        <foreach collection="ids"  open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>
mysql的批量插入:

    <insert id="batchSave">
        inset into employee (name,sn,salary) values
        <foreach collection="emps" separator="," item="e">
            (#{e.name},#{e.sn},#{e.salary})
        </foreach>

    </insert>
查詢操作:

    <select id="query" resultType="Employee">
        SELECT id,name,sn,salary,deptId From employee
        <where>
            <if test="minSalary!=null">
                AND salary >= #{minSalary}
            </if>

            <if test="maxSalary">
                AND salary &lt;= #{maxSalary}
            </if>

            <choose>
                <when test="deptId > 0"> AND deptId = #{deptId}</when>
                <otherwise>AND deptId IS NOT NULL</otherwise>
            </choose>
        </where>
    </select>
bind:可以吧重複的小段代碼提出來用

sql:把重複的代碼包裝起來利用他的id調用

include:文件中插入sql的代碼.

分頁查詢: 回顧一下這一篇博客的知識點

domain

    <select id="query" resultType="Employee">
        SELECT id,name,sn,salary,deptId From employee
        <where>
            <if test="minSalary!=null">
                AND salary >= #{minSalary}
            </if>

            <if test="maxSalary">
                AND salary &lt;= #{maxSalary}
            </if>

            <choose>
                <when test="deptId > 0"> AND deptId = #{deptId}</when>
                <otherwise>AND deptId IS NOT NULL</otherwise>
            </choose>
        </where>
    </select>

mapper

    public interface EmployeeMapper {

        List<Employee> queryForList(QueryObject qo);

        int queryForCount(QueryObject qo);
    }
    <mapper namespace="cn.wolfcode.mybatis.hello.mapper.EmployeeMapper">

        <sql id="base_where">
            <where>
                <if test="keyword != null and keyword != ''">
                    <bind name="keywordLike" value="'%'+keyword+'%'"/>
                    AND (name like #{keywordLike} OR sn LIKE #{keywordLike})
                </if>

                <if test="minSalary!=null">
                    AND salary >= #{minSalary}
                </if>

                <if test="maxSalary!=null">
                    AND salary &lt;= #{maxSalary}
                </if>

                <if test="deptId > 0">
                    AND deptId = #{deptId}
                </if>

            </where>
        </sql>

        <!-- 查詢結果集 -->
        <select id="queryForList" resultType="Employee">
            Select id,name,sn,salary,deptId FROM employee
            <include refid="base_where" />
            <if test="pageSize > 0">
                LIMIT #{start},#{pageSize}
            </if>
        </select>


        <!-- 查詢結果總數 -->
        <select id="queryForCount" resultType="int">
            SELECT COUNT(id) FROM employee
            <include refid="base_where" />
        </select>

    </mapper>

query

@Getter
@Setter
public class EmployeeQueryObject extends QueryObject{

    private String keyword;
    private BigDecimal minSalary;
    private BigDecimal maxSalary;
    private Long deptId = -1L;

    public String getKeyword(){
        return employ2null(keyword);
    }
}
@Getter
public class PageResult {
    private List<?> result;
    private int totalCount;

    private int currentPage = 1;
    private int pageSize = 3;

    private int prevPage;
    private int nextPage;
    private int totalPage;

    public PageResult(List<?> result, int totalCount, int currentPage, int pageSize) {
        this.result = result;
        this.totalCount = totalCount;
        this.currentPage = currentPage;
        this.pageSize = pageSize;

        this.totalPage = totalCount % pageSize == 0 ? totalCount % pageSize : totalCount % pageSize + 1;
        this.prevPage = currentPage - 1 >= 1 ? currentPage - 1 : 1;
        this.nextPage = currentPage + 1 <= totalPage ? currentPage + 1 : totalPage;
        currentPage = currentPage > totalPage ? totalPage : currentPage;
    }
}
@Getter
@Setter
public class QueryObject {
    private int currentPage = 1;
    private int pageSize = 3;

    public int getStart() {
        return (currentPage - 1) * pageSize;
    }

    //如果說字符串爲空字符串,也應該設置爲null
    public String employ2null(String str) {
        return hasLength(str) ? str : null;
    }

    public boolean hasLength(String str) {
        return str != null && !"".equals(str.trim());
    }
}

service

public interface IEmployeeService {

    PageResult query(QueryObject qo);
}

impl

public class EmployeeServiceImpl implements IEmployeeService{

    private EmployeeMapper employeeMapper = MyBatisUtil.getMapper(EmployeeMapper.class);

    public PageResult query(QueryObject qo) {
        int rows = employeeMapper.queryForCount(qo);
        if(rows == 0){
            return new PageResult(Collections.EMPTY_LIST,0,1,qo.getPageSize());
        }
        List<Employee> result = employeeMapper.queryForList(qo);
        return new PageResult(result,rows,qo.getCurrentPage(),qo.getPageSize());
    }
}

MyBatisUtil

    public class MyBatisUtil {

        private static SqlSessionFactory factory = null;

        static{
            InputStream in;
            try {
                //創建SqlSessionFactory對象
                in = Resources.getResourceAsStream("mybatis-config.xml");
                factory = new SqlSessionFactoryBuilder().build(in);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //返回一個SqlSession對象
        public static SqlSession getSession(){
            //默認false不自動提交事務
            return factory.openSession();
        }

        public static <T> T getMapper(Class<T> mapperClass){
            return getSession().getMapper(mapperClass);
        }
    }

mybatis-config.xml

<configuration>

        <properties resource="db.properties">
        </properties>

        <!-- 日誌技術 -->
        <settings>
            <setting name="logImpl" value="LOG4J"/>
        </settings>

        <typeAliases>
            <!-- <typeAlias type="cn.wolfcode.mybatis.hello.User" alias="User"/> -->
            <!-- 一般寫到domain包就可以了,自動爲該包中的類起別名,默認的別名就是簡單類名首字母小寫,其實不區分大小寫 -->
            <package name="cn.wolfcode.mybatis.hello"/>
        </typeAliases>

        <!-- 1:配置數據庫的環境 -->
        <environments default="dev">
            <!-- 開發環境:在以後事務管理器和連接池都是交給Spring框架來管理的 -->
            <environment id="dev">
                <!-- ①:事務管理器 -->
                <transactionManager type="JDBC"/>
                <!-- ②:連接池 -->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
        <!-- 2:關聯映射文件 -->
        <mappers>
            <mapper resource="cn\wolfcode\mybatis\hello\mapper\EmployeeMapper.xml"/>
        </mappers>
</configuration>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章