MyBatis(國稅)


一、MyBatis概要

1.1、ORM介紹

對象關系映射(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),用於實現面向對象編程語言里不同類型系統的數據之間的轉換。它是創建了一個可在編程語言里使用的“虛擬對象數據庫”。簡單來說ORM簡化了應用程序對數據庫的訪問,實現了將數據庫中的數據與程序中的對象進行相互映射,數據庫中的一行記錄可以對應一個對象,一個強類型的集合可以對應一張表。

1.2、常見的ORM框架與庫

自己定義的JDBCUtil缺點:沒有數據庫連接池,影響性能;功能簡單,不能應對復雜需求;沒有緩存機制;
DBUtils:Commons DbUtils是Apache組織提供的一個對JDBC進行簡單封裝的開源工具類庫,使用它能夠簡化JDBC應用程序的開發,同時也不會影響程序的性能。如果自己想學習寫框架,可以從該開源項目開始。

  1. Hibernate:全自動 需要些hql語句,與Struts、Spring組成SSH的搭配
  2. SSH(Struts2、Spring、Hibernate) S2SH
  3. Struts:MVC框架;Hibernate:ORM框架,冬眠;Spring:IOC、AOP…
  4. MyBatis:半自動 自己寫sql語句,可操作性強,小巧,最開始iBatis
  5. JPA:(Java Persistence API)是Sun官方提出的Java持久化規范。它為Java開發人員提供了一種對象/關系映射工具來管理Java應用中的關系數據。

 

1.3、MyBatis

MyBatis本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。2013年11月遷移到Github,網址:https://github.com/mybatis。
iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAO)
MyBatis 是支持普通 SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎所有的JDBC代碼和參數的手工設置以及結果集的檢索。MyBatis 使用簡單的 XML或注解用於配置和原始映射,將接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。
每個MyBatis應用程序主要都是使用SqlSessionFactory實例的,一個SqlSessionFactory實例可以通過SqlSessionFactoryBuilder獲得。SqlSessionFactoryBuilder可以從一個xml配置文件或者一個預定義的配置類的實例獲得。
用xml文件構建SqlSessionFactory實例是非常簡單的事情。推薦在這個配置中使用類路徑資源(classpath resource),但你可以使用任何Reader實例,包括用文件路徑或file://開頭的url創建的實例。MyBatis有一個實用類----Resources,它有很多方法,可以方便地從類路徑及其它位置加載資源。
優點:

  1. 1. 易於上手和掌握。
  2. 2. sql寫在xml里,便於統一管理和優化。
  3. 3. 解除sql與程序代碼的耦合。
  4. 4. 提供映射標簽,支持對象與數據庫的orm字段關系映射
  5. 5. 提供對象關系映射標簽,支持對象關系組建維護
  6. 6. 提供xml標簽,支持編寫動態sql。

git地址:https://github.com/mybatis/

下載源碼:https://github.com/mybatis/mybatis-3/releases

下載Jar包:https://github.com/mybatis/mybatis-3

官方文檔:http://www.mybatis.org/mybatis-3/zh/index.html

MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數的手工設置以及對結果集的檢索封裝。MyBatis可以使用簡單的XML或注解用於配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成數據庫中的記錄。

二、MyBatis示例

2.1、MyBatis基礎

結果:

添加包

mybatis.xml 環境配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
                <property name="username" value="tax"/>
                <property name="password" value="orcl"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/tax/mapping/bookMapping.xml"/>
    </mappers>
</configuration>

 

Book.java POJO對象

package com.tax.model;

/**圖書實體 Bean POJO*/
public class Book {
    /**編號*/
    private int id;
    /**書名*/
    private String title;
    /**類型*/
    private String typename;
    /**價格*/
    private Double price;
    /**狀態*/
    private String state;

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", typename='" + typename + '\'' +
                ", price=" + price +
                ", state='" + state + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getTypename() {
        return typename;
    }

    public void setTypename(String typename) {
        this.typename = typename;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
}

bookMaping.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.tax.mapping.bookMapper">
    <!--
        根據id查詢得到一個book對象
     -->
    <select id="getBookById" resultType="com.tax.model.Book">
        select id, title, typename, price, state from book where id=#{id}
    </select>
    <select id="getAllBooks" resultType="com.tax.model.Book">
        select id, title, typename, price, state from book
    </select>
</mapper>

BookDao 數據訪問

package com.tax.dao;

import com.tax.model.Book;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

/**圖書數據訪問*/
public class BookDao {
    /**獲得圖書通過編號*/
    public Book getBookById(int id){
        //將mybatis的配置文件轉換成輸入流,讀配置文件
        InputStream cfg=this.getClass().getClassLoader().getResourceAsStream("mybatis.xml");
        //根據配置文件構建會話工廠
        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(cfg);
        //創建會話
        SqlSession session=factory.openSession();
        //調用方法getBookById帶入參數1獲得單個圖書對象
        Book book=session.selectOne("com.tax.mapping.bookMapper.getBookById",id);
        //關閉會話
        session.close();
        return book;
    }

    public static void main(String[] args) {
        BookDao dao=new BookDao();
        //輸出
        System.out.println(dao.getBookById(3));
    }
}

運行結果:

Book{id=3, title='Java並發編程的藝術', typename='軟件工程', price=45.4, state='未借出'}

 2.2、JUnit單元測試

添加JUnit依賴

添加測試的包與類

package com.tax.test;

import com.tax.dao.BookDao;
import com.tax.model.Book;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Assert.*;

public class BookDaoTest {
    @Test
    public void getBookById(){
        BookDao dao=new BookDao();
        Book book=dao.getBookById(1);
        System.out.println(book);
        //斷言,期待1,實際2
        //Assert.assertEquals(1,2);
        //不為空就通過
        Assert.assertNotNull(book);
    }

}

 

其它注解

import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

public class CalculatorTest {

    private static Calculator calculator = new Calculator();

    //每個方法測試前調用
    @Before
    public void clearCalculator() {
        calculator.clear();
    }
    
    //每個方法測試完以后調用
    @After 
    public void tearDown()  
    { 
    }
    
    //@Test:測試方法,表明這是一個測試方法。在Junit中將會自動被執行。
    @Test
    public void add() {
        calculator.add(1);
        calculator.add(1);
        //第一個參數是預期的,第二個參數是真實的  
        assertEquals(calculator.getResult(), 2);
    }

    @Test
    public void subtract() {
        calculator.add(10);
        calculator.substract(2);
        //第一個參數是預期的,第二個參數是真實的  
        assertEquals(calculator.getResult(), 8);
    }

    //給測試函數設定一個執行時間,超過了這個時間(400毫秒),它們就會被系統強行終止
    @Test(timeout=400)
    public void divide() {
        calculator.add(8);
        calculator.divide(2);
        //第一個參數是預期的,第二個參數是真實的  
        assert calculator.getResult() == 5;
    }

    //使用注釋來聲明該異常是預期的,異常測試是Junit4中的最大改進
    @Test(expected = ArithmeticException.class)
    public void divideByZero() {
        calculator.divide(0);
    }
    //@Ignore:忽略的測試方法,標注的含義就是“某些方法尚未完成,暫不參與此次測試”
    @Ignore("not ready yet")
    @Test
    public void multiply() {
        calculator.add(10);
        calculator.multiply(10);
        //第一個參數是預期的,第二個參數是真實的  
        assertEquals(calculator.getResult(), 100);
    }
}

注解

@Test 測試方法,表明這是一個測試方法。在Junit中將會自動被執行。
@Test(timeOut=400) 給測試函數設定一個執行時間,超過了這個時間(400毫秒),它們就會被系統強行終止
@Test(expected = ArithmeticException.class) 使用注釋來聲明該異常是預期的,異常測試是Junit4中的最大改進
@Ignore("not ready yet") 忽略的測試方法,標注的含義就是“某些方法尚未完成,暫不參與此次測試”
@Before 每個方法測試前調用
@After 每個方法測試完以后調用
@BeforeClass 每個類運行前調用,並且只調用一次
@AfterClass 每個類運行后調用,並且只調用一次

2.3、XML+接口實現CRUD

BookDao接口

package com.tax.dao2;

import com.tax.model.Book;

import java.util.List;
public interface BookDao {
    public Book getBookById(int id);

    public List<Book> getAllBooks();

    public int add(Book book);

    public int update(Book book);

    public int deleteById(int id);
}

 

MyBatis工具類

package com.tax.dao2;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public abstract class MyBatisUtil {
    
    //GC不理static
    private static SqlSessionFactory factory=null;
    public static SqlSessionFactory getSqlSessionFactory(){
        if(factory==null){
        // 獲得環境配置文件流
        InputStream config = MyBatisUtil.class.getClassLoader().getResourceAsStream("mybatis.xml");
        // 創建sql會話工廠
        factory = new SqlSessionFactoryBuilder().build(config);
        }
        return factory;
    }
    
    //獲得會話
    public static SqlSession getSession(){
        return getSqlSessionFactory().openSession(true);
    }
    
    /**
     * 獲得得sql會話
     * @param isAutoCommit 是否自動提交,如果為false則需要sqlSession.commit();rollback();
     * @return sql會話
     */
    public static SqlSession getSession(boolean isAutoCommit){
        return getSqlSessionFactory().openSession(isAutoCommit);
    }
    
}

 

Book表映射文件

<?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.tax.dao2.BookDao">
    <!--
        根據id查詢得到一個book對象
     -->
    <select id="getBookById" resultType="Book">
        select id, title, typename, price, state from book where id=#{id}
    </select>

    <select id="getAllBooks" resultType="Book">
        select id, title, typename, price, state from book
    </select>

    <insert id="add" parameterType="Book">
      insert into book (id, title, typename, price, state) values(seq_book_id.nextval, #{title}, #{typename}, #{price}, #{state})
    </insert>

    <update id="update"  parameterType="Book">
        update book set title=#{title},typename=#{typename},price=#{price},state=#{state} where id=#{id}
    </update>

    <delete id="deleteById">
        delete from book where id=#{id}
    </delete>
</mapper>

 

BookDaoImpl實現

package com.tax.dao2;

import com.tax.model.Book;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class BookDaoImpl implements BookDao {
    @Override
    public Book getBookById(int id) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSession();
            BookDao dao = session.getMapper(BookDao.class);
            return dao.getBookById(id);
        } finally {
            session.close();
        }
    }

    @Override
    public List<Book> getAllBooks() {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSession();
            BookDao dao = session.getMapper(BookDao.class);
            return dao.getAllBooks();
        } finally {
            session.close();
        }
    }

    @Override
    public int add(Book book) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSession();
            BookDao dao = session.getMapper(BookDao.class);
            return dao.add(book);
        } finally {
            session.close();
        }
    }

    @Override
    public int update(Book book) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSession();
            BookDao dao = session.getMapper(BookDao.class);
            return dao.update(book);
        } finally {
            session.close();
        }
    }

    @Override
    public int deleteById(int id) {
        SqlSession session = null;
        try {
            session = MyBatisUtil.getSession();
            BookDao dao = session.getMapper(BookDao.class);
            return dao.deleteById(id);
        } finally {
            session.close();
        }
    }
}

 

測試文件

package test.com.tax.dao2;

import com.tax.dao2.BookDao;
import com.tax.dao2.BookDaoImpl;
import com.tax.model.Book;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;

/**
 * BookDaoImpl Tester.
 *
 * @author <Authors name>
 * @version 1.0
 * @since <pre>03/15/2018</pre>
 */
public class BookDaoImplTest {

    BookDao dao;

    @Before
    public void before() throws Exception {
        dao = new BookDaoImpl();
    }

    @After
    public void after() throws Exception {
    }

    /**
     * Method: getBookById(int id)
     */
    @Test
    public void testGetBookById() throws Exception {
        System.out.println(dao.getBookById(3));
    }

    /**
     * Method: getAllBooks()
     */
    @Test
    public void testGetAllBooks() throws Exception {
        for (Book book:dao.getAllBooks()) {
            System.out.println(book);
        }
    }

    /**
     * Method: add(Book book)
     */
    @Test
    public void testAdd() throws Exception {
        Book book=new Book();
        book.setTypename("計算機");
        book.setState("未借出");
        book.setTitle("Spring 入門到放棄");
        book.setPrice(23.5);
        Assert.assertEquals(1,dao.add(book));
    }

    /**
     * Method: update(Book book)
     */
    @Test
    public void testUpdate() throws Exception {
        Book book=dao.getBookById(49);
        book.setTypename("從入門到精通");
        Assert.assertEquals(1,dao.update(book));
    }

    /**
     * Method: deleteById(int id)
     */
    @Test
    public void testDeleteById() throws Exception {
        Assert.assertEquals(1,dao.deleteById(49));
    }


} 

 

結果:

 2.4、基於注解實現CRUD

使用注解不再需要mapping文件

BookDao接口如下:

package com.tax.dao;

import com.tax.model.Book;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;
public interface BookDao {
    @Select("select id, title, typename, price, state from book where id=#{id}")
    public Book getBookById(int id);

    @Select("select * from book")
    public List<Book> getAllBooks();

    @Insert("insert into book (id, title, typename, price, state) values(seq_book_id.nextval, #{title}, #{typename}, #{price}, #{state})")
    public int add(Book book);

    @Update("update book set title=#{title},typename=#{typename},price=#{price},state=#{state} where id=#{id}")
    public int update(Book book);

    @Delete("delete from book where id=#{id}")
    public int deleteById(int id);
}

mybatis.xml文件如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
                <property name="username" value="tax"/>
                <property name="password" value="orcl"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="com.tax.dao.BookDao"/>
    </mappers>
</configuration>

其它內容與2.3節一樣。

2.5、別名與數據源

bookMapping.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.tax.dao2.BookDao">
    <!--
        根據id查詢得到一個book對象
     -->
    <select id="getBookById" resultType="B">
        select id, title, typename, price, state from book where id=#{id}
    </select>

    <select id="getAllBooks" resultType="B">
        select id, title, typename, price, state from book
    </select>

    <insert id="add" parameterType="Book">
      insert into book (id, title, typename, price, state) values(seq_book_id.nextval, #{title}, #{typename}, #{price}, #{state})
    </insert>

    <update id="update"  parameterType="Book">
        update book set title=#{title},typename=#{typename},price=#{price},state=#{state} where id=#{id}
    </update>

    <delete id="deleteById">
        delete from book where id=#{id}
    </delete>
</mapper>

mybatis.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias type="com.tax.model.Book" alias="B"></typeAlias>
        <package name="com.tax.model"></package>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
                <property name="username" value="tax"/>
                <property name="password" value="orcl"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/tax/mapping/bookMapping.xml"/>
    </mappers>
</configuration>

數據源

db.properties

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
username=tax
password=orcl

mybatis.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="db.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper class="com.tax.dao.BookDao"/>
    </mappers>
</configuration>

 2.6、Java Web中整合MyBatis(展示與刪除功能)

項目結構:

BookServlet

package com.tax.action;

import com.tax.dao.BookDao;
import com.tax.dao.BookDaoImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/BookServlet")
public class BookServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //設置編碼
        request.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        response.setCharacterEncoding("utf-8");

        //獲得action類型
        String act=request.getParameter("act");
        //如果當前的動作是刪除
        if(act.equals("delete"))
        {
            //獲得URL中要刪除的圖書編號
            int id=Integer.parseInt(request.getParameter("id"));
            BookDao dao=new BookDaoImpl();
            if(dao.deleteById(id)>0){  //執行刪除並成功
                request.setAttribute("msg","刪除成功!");
            }else{
                request.setAttribute("msg","刪除失敗!");
            }
            //轉發到index.jsp頁面
            request.getRequestDispatcher("index.jsp").forward(request,response);
        }else if(act.equals("edit")){

        }else{
            response.sendRedirect("index.jsp");
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

 

index.jsp

<%@ page import="com.tax.dao.BookDao" %>
<%@ page import="com.tax.dao.BookDaoImpl" %>
<%@ page import="com.tax.model.Book" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    BookDao dao = new BookDaoImpl();
    List<Book> books = dao.getAllBooks();
%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>圖書列表</title>
    <style>
        body{
            font-size:14px;
        }
        #tabBooks {
            width: 80%;
        }

        #tabBooks, #tabBooks td {
            border-collapse: collapse;
        }
        .red{
            color:red;
        }
        .green{
            color:green;
        }
    </style>
</head>
<body>
<h2>圖書列表</h2>
<table border="1" id="tabBooks">
    <tr>
        <td>
            <input type="checkbox" id="chbAll"/>
        </td>
        <td>序號</td>
        <td>書名</td>
        <td>價格</td>
        <td>類型</td>
        <td>狀態</td>
        <td>操作</td>
    </tr>
    <%for (int i = 0; i < books.size(); i++) {%>
    <tr>
        <td>
            <input type="checkbox" name="id" value=""/>
        </td>
        <td>
            <%=i + 1%>
        </td>
        <td><%=books.get(i).getTitle()%>
        </td>
        <td><%=books.get(i).getPrice()%>
        </td>
        <td><%=books.get(i).getTypename()%>
        </td>
        <td class="<%=books.get(i).getState().equals("未借出")?"green":"red"%>">
            <%=books.get(i).getState()%>
        </td>
        <td>
            <a href="BookServlet?act=delete&id=<%=books.get(i).getId()%>" class="delete" onclick="return isDel()">刪除</a>
        </td>
    </tr>
    <%}%>
</table>
<script>
//    var items=document.querySelectorAll(".delete");
//    for(var i=0;i<items.length;i++){
//        items[i].onclick=function () {
//            return confirm("您確定要刪除嗎?");
//        }
//    }

    function isDel() {
        return confirm('您確定要刪除嗎?');
    }
</script>
</body>
</html>

 結果:

 2.7、參考代碼

https://git.coding.net/zhangguo5/WebReadMyBatis.git

三、MyBatis總結

使用jdbc開發時,和mybatis相比的不足 
1,數據庫連接,使用時就創建,不使用就釋放,對數據庫進行頻繁連接開關和關閉,造成數據庫資源浪費,影響數據庫的性能 
解決:使用數據庫連接池管理數據庫的連接 
2,sql語句使用硬編碼在java程序中,修改sql語句,就需要重新編譯java代碼,不利於系統維護 
解決:把sql語句放在xml配置文件中,修改sql語句也不需要重新編譯java代碼 
3,向預編譯語句PreparedStatement中設置參數,對占位符位置和設置參數值,硬編碼,修改sql語句也不需要重新編譯java代碼 
解決:把sql語句和占位符設置參數值放在xml配置文件中 
4,從result中遍歷結果集數據時,存在硬編碼,將獲取表的字段進行硬編碼 
解決:將查詢的結果集,自動映射成 java對象

二 mybatis框架,是一個持久層框架,是apache下的頂級項目 
mybatis讓程序員將主要精力放在sql上,通過mytabis提供的映射方式,自動生成滿足需要的sql語句 
mybatis可以向PreparedStatement中輸入參數自動進行輸入映射,將查詢結果集靈活的映射成Java對象(輸出映射),輸入映射和輸出映射這是mybatis的核心 
mybatis框架執行流程圖 
這里寫圖片描述
三 mybatis的工作環境搭建和架構示意圖 
這里寫圖片描述 
四 mybatis的開發 
1.映射文件的開發如下圖 
這里寫圖片描述
2,映射文件配置好了之后,還需要在全局配置文件sqlMapConfig.xml中添加映射文件 
這里寫圖片描述 
3,sqlsession會話去執行操作查詢數據庫映射文件,下圖中的錯誤糾正為’%${value}%’ 
這里寫圖片描述
查詢出的是單條記錄使用selectOne,下圖中的錯誤糾正為把“1”改為int類型的1 
sqlsession.selectOne(“test.findUserById”, 1); 
這里寫圖片描述 
查詢出的是多條記錄使用selectList 
sqlsession.selectList(“test.findUserByName”, “hello”); 
這里寫圖片描述 
4,添加用戶映射文件配置如下: 
這里寫圖片描述
程序代碼: 
這里寫圖片描述
5,總結: 
這里寫圖片描述 
四 mybatis開發dao方法 
mybatis的配置文件不變 
1,先使用原型的開發dao方法 
開發接口 
這里寫圖片描述 
2, 開發接口實現 
這里寫圖片描述
3, 測試代碼 
這里寫圖片描述
4,總結 
這里寫圖片描述 
五 mybatis利用mapper代理開發dao(重點掌握) 
mapper代理開發,就不需要接口的實現類,只需要接口UserMapper.java和映射文件UserMapper.xml就可以了,但是遵循一定的開發規范: 
1,在UserMapper.xml文件中namespace等於UserMapper接口地址 
這里寫圖片描述 
2,UserMapper.java接口中的方法名要和UserMapper.xml中的statement的id一致 
3,UserMapper.java接口中的方法輸入參數要和UserMapper.xml中的statement的parameterType指定的類型一致 
4,UserMapper.java接口中的方法的返回值類型要和UserMapper.xml中的statement的resultType指定的類型一致 
測試代碼: 
這里寫圖片描述 
上圖畫線區域:這里沒有實現接口的實現類,而是使用mybatis生成的代理對象來生成UserMappper接口的對象,從而能夠調用其方法

mapper代理開發dao出現的問題總結: 
1,代理對象內部調用selectOne或selectList 
如果mapper方法返回單個pojo對象(非集合對象),代理對象內部通過selectOne查詢數據庫,也可以使用selectList查詢。 
如果mapper方法返回集合對象,代理對象內部通過selectList查詢 數據庫,不能使用selectOne查詢,否則會出錯。 
問題是: 編譯期間不會報錯,二者容易寫錯使用。 
2,mapper接口方法參數只有一個 
根據規范編寫的代理對象的傳入參數只能有一個(mapper.xml文件中的parameterType參數只有一個),不利於系統的擴展 
解決:即使mapper接口中只有一個參數,可以使用包裝類型的pojo滿足不同的業務方法需求

mybatis的一些細節剖析:

1,全局配置文件sqlMapConfig.xml中配置內容如下:

  1. properties(屬性) 
    注意:mybatis將按照下面的順序來加載屬性: 
    (1)在properties元素體內定義的屬性首先被讀取。(可以在此屬性中加入jdbc的配置文件db.properties),在sqlMapConfig.xml中就不需要對數據庫連接參數進行硬編碼了。 

  2. settings全局參數設置 
    mybatis框架運行時可以調整一些運行參數,會影響mybatis運行行為,所以建議不要隨便修改 
    比如:二級緩存,開啟延時加載。。。

  3. typeAliases(別名) 重點掌握 
    這里寫圖片描述
  <typeAliases> <!--針對單個別名定義 type:類型的路徑 alias:別名 --> <typeAlias type="com.jary.mybatis.po.User" alias="user" /> <!--還可以進行批量別名定義 指定包名,mybatis自動掃描包中的po類 --> <package name="com.jary.mybatis.po" /> </typeAliases> 

上面的別名定義后,在mapper.xml中就可以這樣使用了 

user代替了輸出結果類型com.jary.mybatis.po.User。

4.映射文件(mapper)

通過resource加載單個的映射文件

<mapper resource="mapper/UserMapper.xml" />
  • 1

通過mapper接口加載單個mapper,要遵循一定的規范: 
(1)前提是使用mapper代理開發(已經有4個規范) 
(2)需要將mapper接口類名和mapper.xml映射文件名稱保持一致,且在同一目錄下 
這里寫圖片描述

<mapper class="com.jary.mybatis.mapper.UserMapper" />
  • 1

通過批量加載mapper(推薦使用):實現條件是 
要滿足mapper接口加載映射文件和使用mapper代理開發同時滿足 
這里寫圖片描述 
mybatis的一些細節剖析結束

mybatis的核心輸入映射和輸出映射開始:

輸入映射 
通過parameterType指定輸入參數類型,類型可以是簡單類型、hashmap、pojo的包裝類型 
1,傳遞pojo的包裝對象 
(1)需求 
完成用戶信息的綜合查詢,需要傳入查詢條件復雜(可能包括用戶信息,商品信息,商品訂單等),這樣靠一個parameterType只能傳入一個輸入參數,所有需要pojo的包裝類型來實現 
(2)定義包裝類型pojo 
針對上面的需求,在包裝類型的pojo中把這些復雜的查詢條件包裝進去,定義包裝類UserQueryVo,把需要查詢的條件全部定義在里面 
這里寫圖片描述 
上圖中標注的用戶查詢條件使用的是User的擴展類(因為User類一般是由逆向工程自動生成的,不要進行修改,所有使用的擴展類來實現) 
映射文件UserMapper.xml配置 
這里寫圖片描述 
UserMapper.java接口文件的配置 
這里寫圖片描述 
上圖中,把包裝類作為參數傳入,返回值是一個用戶列表所以用list集合接收

測試代碼如下圖: 
這里寫圖片描述

輸出映射 
1,resultType 
使用resultType進行輸出映射時,只有查詢輸出結果列名和pojo中的屬性名一致才可以,映射成功 
如果查詢出來的列名和pojo中的屬性名沒有一個一致的,就不會創建pojo對象 
如果查詢出來的列名和pojo中的屬性名有一個一致,就會創建pojo對象 
輸出pojo對象和pojo列表 
不管是輸出的pojo單個對象還是一個列表(list中包含pojo),在mapper.xml中resultType指定的類型是一樣的 
在mapper.java指定的方法返回值類型不一樣: 
(1)輸出單個pojo對象,方法返回值是個單個對象類型 
(2)輸出pojo對象list,方法返回值就是list對象類型 
在動態代理對象中,是根據mapper方法的返回值類型來確定是調用selectOne(返回單個對象)還是selectList(返回集合對象) 
2,resultMap 
使用resultMap進行映射時,查詢結果列名和pojo的屬性名不一致時,resultMap會對列名和pojo屬性名進行映射,保證其成功映射 
使用resultMap需要這二步: 
(1)定義resultMap 
這里寫圖片描述 
(2)使用resultMap作為statement的輸出映射類型 
這里寫圖片描述 
mybatis的核心輸入映射和輸出映射結束:

mybatis的動態sql和sql片段開始:

動態sql 
mybatis核心就是對sql語句進行靈活操作,通過表達式進行判斷,對sql進行靈活拼接和組裝。 
需求:用戶信息查詢的綜合信息需要使用動態sql 
對查詢條件進行判斷,如果出入參數不為空,才進行拼接 
這里寫圖片描述 
測試代碼需要注意的是如下圖: 
這里寫圖片描述 
如果不設置某個值,條件將不拼接在sql中

sql片段 
需求:將上面的動態sql(重復的sql語句)抽取出來做成一個片段,方便其他statement語句重復使用sql片段 
定義sql片段 
使用sql片段 
這里寫圖片描述

使用foreach標簽遍歷 
給sql傳入數組或者集合時,mybatis使用foreach解析 
需求:在用戶信息的綜合查詢中增加多個id傳入 
sql語句如下: 
select * from user where id=1 or id=3 or id=5 
也可以使用select * from user where id in(1,3,5) 
這里寫圖片描述 
mybatis的動態sql和sql片段結束

mybatis高級映射開始: 
一、 高級映射一對一查詢(使用到assocition標簽實現關聯對象的一對一查詢映射),分別使用resultType和resultMap,並且比較二者的區別 
這里寫圖片描述 
還有一點就是,resultType查詢關聯列表結果列如果和pojo屬性名不一致,需要自己創建擴展類(繼承包括結果集列名多的pojo對象,這樣可以少寫一點屬性名)。resultMap則不需要創建擴展類,而是把關聯信息的對象注入,從而實現結果集列名和pojo屬性名保持一致。 
二、高級映射一對多查詢(使用collection標簽來實現關聯對象的一對多查詢映射),一對多,就是關聯的對象查詢結果是一個List集合 
開發步驟: 
(1)首先寫sql語句 
需求:查詢訂單及訂單明細信息(一個訂單包含多個訂單明細,所以一對多) 
主表:訂單表 
關聯表:訂單明細表 
經過之前一對一查詢(用戶的訂單)的分析,我們只需要在此基礎上關聯訂單明細表即可。 
這里寫圖片描述 
(2)pojo類(resultType時用到擴展類,這里我們使用resultMap不需要包裝類) 
這里寫圖片描述 
(3)mapper.xml(這里我們使用了resultMap的繼承,不需要重新關聯訂單表和用戶表,通過繼承之前的一對一(用戶查詢訂單)所寫的二個表,可以減少大量的重復代碼。同時使用了collection集合標簽將關聯查詢出的多條記錄映射到List集合中) 
這里寫圖片描述
(4)mapper.java 
這里寫圖片描述

一對多查詢總結: 
mybatis使用resultMap的collection(resultType沒有此標簽)對關聯查詢的多條記錄映射到一個list集合中。 
使用resultType通過雙重循環遍歷可以實現,去除重復記錄,將訂單明細映射在orderdetail中(了解) 
多對多查詢實例和上邊類似。主要是搞清楚各個表之間的對應關系,訂單的collection中嵌套訂單明細的collection,而訂單明細的collection中嵌套商品信息。

mybatis高級映射結束

mybatis的延遲加載和緩存技術開始 
mybatis一級緩存 
這里寫圖片描述 
mybatis的二級緩存

mybatis默認是沒有開啟二級緩存的。 
開啟二級緩存需要在mybatis的全局配置文件sqlMapConfig.xml中加入 

除了開啟二級緩存開關外,還需要在各自的mapper.xml中開啟二級緩存。 
這里寫圖片描述

原理圖: 
這里寫圖片描述 
如上圖:sqlsession1去查詢id為1的用戶信息,查詢到用戶信息就會查詢數據存放在二級緩存區域(hashmap)中 
sqlsession2去查詢id為1的用戶信息,首先去緩存中查找是否存在數據,如果存在就直接從二級緩存中取出數據。 
二級緩存和一級緩存的區別:二級緩存的范圍更大,多個sqlsession 
可以共享usermapper的二級緩存。 
二級緩存是根據mapper的namespace來划分的,相同namaspace下的mapper共享二級緩存,反之 
如果sqlsession3去執行相同mapper下sql,並執行commit()操作,則清空該命名空間下的二級緩存

二級緩存的測試代碼:

這里寫圖片描述

上面塗黃部分要特別注意,sqlsession關閉時才可以把數據寫到二級緩存區域中,如果本namespace下的sqlsession執行了commit()操作,二級緩存就會清空

禁用二級緩存 
也可以禁用單個查詢的二級緩存,這樣要保證每次查詢的都是最新數據。 
這里寫圖片描述

刷新二級緩存(就是清空緩存,切記) 
這里寫圖片描述 
總結:一般情況下,執行commit()操作之后,都要刷新緩存,因此flushCache都設為true,來避免數據的臟讀。

mybatis cache的參數設置 
flushInterval(刷新間隔),可以為任意整數,單位為毫秒值,這個比較有用。

mybatis和第三方分布式緩存框架整合(ehcache,redis,memcache) 
mybatis在緩存方面還是比較弱,特別是分布式緩存不支持 
這里寫圖片描述 
我們的系統為了提高系統並發,性能,一般對系統進行分布式部署(集群部署方式)

整合方法 
mybatis提供了一個cache接口,如果要實現自己的緩存邏輯,實現cache接口即可 
mybatis和ehcache整合,mybatis和ehcache整合包中提供了一個cache接口的實現類。 
這里寫圖片描述

二級緩存的應用場景(實際開發中用 刷新間隔) 
這里寫圖片描述

二級緩存額局限性 
這里寫圖片描述 
細粒度緩存,就是修改一個商品信息(即執行commit()方法),只修改緩存中這一個商品的信息,其余的信息不清空。

mybatis的延遲加載和緩存技術結束

mybatis和spring的整合(重點掌握)開始

1、整合的思路: 
(1)首先需要spring通過單例方式管理sqlSessionFactory 
(2)spring和mybatis整合生成代理對象,使用SqlSessionFactory創建sqlSession會話(此步是由spring和mybatis整合自動完成) 
(3)持久層的mapper,dao都需要由spring來管理 
2、環境的搭建 
這里寫圖片描述 
上面的sqlmap目錄下的User.xml是為了原始dao開發使用的。還要加載spring,mybatis,mybatis-srping等jar包。 
3、在spring的配置文件中配置sqlSessionFactory和數據源 
sqlSessionFactory在mybatis和spring的整合包下 
這里寫圖片描述 
上圖中:使用C3P0配置數據庫連接池,屬性參數名要按照規定寫,不能自己定義,否則會報錯,而使用dbcp就可以自定義參數名,這點注意。 
在加載配置文件時,都要加上類路徑名classpath 
在使用原始dao開發時,屬性name值要與UserDaoImpl類中變量名一致(特別是大小寫) 
4、*原始Dao的開發(和spring整合后)* 
4.1 User.xml(也稱mapper.xml更准確) 
這里寫圖片描述 
和spring整合后,需要使用spring來管理mapper,spring配置文件為applicationContext.xml 
還有mybatis的配置文件來加載User.xml 
這里寫圖片描述 
4.2 UserDAO 
這里寫圖片描述 
基本上不用改變 
4.3 UserDaoImpl(重點在Dao的實現類上) 
這里寫圖片描述
上圖中的代碼最重要的就是繼承了SqlSessionDaoSupport通過this.getSqlSession()來得到SqlSession會話 
這里也不需要寫sqlSession的事務提交(更新操作不用寫)和sqlSession關閉 
4.4 測試代碼 
這里寫圖片描述

5、使用mapper代理來開發 (mybatis和spring整合后) 
和利用原始dao開發差不多,只是不需要dao接口的實現類 
而是根據一個規范來實現dao接口生成代理對象

5.1規范: 
(1)mapper.xml中的namespace命名空間等於mapper.java的全路徑名 
這里寫圖片描述
(2)mapper.xml和mapper.java應在同一個目錄下 
這里寫圖片描述 
(3)mapper.xml中的statement語句的輸入參數paramType類型應與mapper.java中方法中傳遞的參數類型一致 
這里寫圖片描述 
這里寫圖片描述
(4)mapper.xml中的statement語句的輸出參數resultType類型應與mapper.java中方法返回值類型一致 
這里寫圖片描述 
這里寫圖片描述
5.2 讓spring來管理mapper,在配置文件中 
這里寫圖片描述 
重點在這里,使用mybatis和spring的整合包中MapperFactoryBean來實現mapper接口生成代理對象 
屬性值有mapperInterface和sqlSessionFactory 
總結:此方法存在一個大問題,需要針對每個mapper進行配置,太麻煩 
終極解決方案: 通過mapper批量掃描,從mapper包中掃描出mapper接口,自動創建代理對象並且在spring容器中注冊 
這里寫圖片描述

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
  • 1

上面代碼,不能使用ref而是使用value,剛開始用錯了。 
開發中推薦使用自動掃描, 
mybatis和spring的整合(重點掌握)結束 
mybatis的逆向工程(了解會用就行) 
這里寫圖片描述
generator.xml的配置,這里要記住,上圖中最下邊table后面的一長串值等於false的屬性,是為了不生成其他與我們無關的example等代碼 
下面需要mybatis-generator-core-1.3.2.jar和generator.xml文件在同於目錄下,並且建立src目錄接收生成的文件 
這里寫圖片描述
生成后的如下圖 
這里寫圖片描述 
沒有了example的無用類了,比較干凈,推薦使用

1.接口綁定:兩種方法,基於注解或者基於xml文檔mapper,但要注意mapper的namespace要與接口路徑完全一致。

2.orm格式轉換:通過設置resultMap和ResultType,將數據庫中的記錄轉換為代碼的bean對象。得到list或者對象。

3.通過parameterType接收參數,進行動態sql生成。運用ognl表達式

4.走緩存,設置二級緩存。設置二級緩存源。

5.為什么要通過orm框架來走緩存呢?因為自己配置緩存策略相對復雜,比如當insert/update/delete時,要清除相應的緩存。當某些情況select又要添加進緩存。

6.orm框架,orm框架,它是怎么進行對象和數據庫中表的轉換的呢?答:數據庫中的表要與代碼中的類一一對應,包括屬性。這樣不就能進行匹配轉換了嘛。

5.返回list,必須要配置resultMAp

6.insert操作時,要注意主鍵 主鍵生成策略,要設置useGeneraterKey = true,和 keyProperty="id",指定哪個是主鍵

<insert id="addUser" parameterType="User" 
        useGeneratedKeys="true" keyProperty="id"> 
        insert into user(userName,userAge,userAddress)  
             values(#{userName},#{userAge},#{userAddress})  
    </insert>

7.spring在於mybatis集成時,spring負責什么呢?誰來維護datasource,誰來建立sqlSessionFactory?

答:spring作為多個框架的粘合劑,spring負責建立datasource,sqlsessionFactpry。充分利用spring的ioc和aop功能。

復制代碼
 spring 配置文件:applicationContext.xml 

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">//spring管理配置datasource <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="password"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> //spring管理配置sqlsessionFactory <!--dataSource屬性指定要用到的連接池--> <property name="dataSource" ref="dataSource"/> <!--configLocation屬性指定mybatis的核心配置文件--> <property name="configLocation" value="config/Configuration.xml"/> </bean>
復制代碼

8.Mybatis的dao實現接口(接口綁定),是由mybatis來實現的,那又怎么來使用這個實現類呢?

答:當然是注冊到spring里了,作為一個bean使用。

即:mybatis的dao實現類,也都要注冊到spring的ioc容器中,以便利用spring的ioc和aop功能。

注意此時dao實現類,的具體類是mybatis固定的org.mybatis.spring.mapper.MapperFactoryBean類,這個類專門用來生成具體的dao實現類。

但要記住,一切的增刪改查都是通過session來進行的,所以dao實現類要di依賴注入sqlSessionFactory這個屬性。

再利用mapperInterface指定具體的mapper接口類。

復制代碼
spring 配置文件:applicationContext.xml 

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!--sqlSessionFactory屬性指定要用到的SqlSessionFactory實例--> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> <!--mapperInterface屬性指定映射器接口,用於實現此接口並生成映射器對象--> <property name="mapperInterface" value="com.yihaomen.mybatis.inter.IUserOperation" /> </bean>
復制代碼

9.即:mybatis的dao實現類,也都要注冊到spring的ioc容器中,以便利用spring的ioc和aop功能。

10.spring的配置文件applicationContext.XML負責配置與數據庫相關,與mybatis sqlSessionFaction 整合,掃描所有mybatis mapper 文件等相關內容。

事務管理器也在spring的配置文件中配置,同時要依賴注入datasource屬性

 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
    </bean>

11.mybatis的分頁功能,可以自己利用mysql代碼實現,也可以利用mybatis分頁插件,如pageHelper

12.mybatis的傳入參數只能是一個,只能有1個。可以是各種Java的基本數據類型:包含int,String,Date等。基本數據類型作為傳參,只能傳入一個。通過#{參數名} 即可獲取傳入的值 ,復雜數據類型:包含JAVA實體類、Map。通過#{屬性名}或#{map的KeyName}即可獲取傳入的值,但是如果想傳入一個collection怎么辦呢?

經查找后發現可以使用mapper配置文件中的foreach語句,借用別人寫的文章:

13. foreach

對於動態SQL 非常必須的,主是要迭代一個集合,通常是用於IN 條件。List 實例將使用“list”做為鍵,數組實例以“array” 做為鍵。

foreach元素是非常強大的,它允許你指定一個集合,聲明集合項和索引變量,它們可以用在元素體內。它也允許你指定開放和關閉的字符串,在迭代之間放置分隔符。這個元素是很智能的,它不會偶然地附加多余的分隔符。

14. 在Java實體對象對中,一對多可以根據List和Set來實現,兩者在mybitis中都是通過collection標簽來配合使用

 

15.

一對一關聯

根據班級id查詢班級信息(帶老師的信息)
10         ##1. 聯表查詢
11         SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;
復制代碼
<select id="getClass" parameterType="int" resultMap="ClassResultMap">
24         select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
25     </select>
26     <!-- 使用resultMap映射實體類和字段之間的一一對應關系 -->
27     <resultMap type="me.gacl.domain.Classes" id="ClassResultMap">
28         <id property="id" column="c_id"/>
29         <result property="name" column="c_name"/>
30         <association property="teacher" javaType="me.gacl.domain.Teacher">
31             <id property="id" column="t_id"/>
32             <result property="name" column="t_name"/>
33         </association>
34     </resultMap>
復制代碼
<!-- 
37     方式二:嵌套查詢:通過執行另外一個SQL映射語句來返回預期的復雜類型
38         SELECT * FROM class WHERE c_id=1;
39         SELECT * FROM teacher WHERE t_id=1   //1 是上一個查詢得到的teacher_id的值
40     -->
41      <select id="getClass2" parameterType="int" resultMap="ClassResultMap2">
42         select * from class where c_id=#{id}
43      </select>
44      <!-- 使用resultMap映射實體類和字段之間的一一對應關系 -->
45      <resultMap type="me.gacl.domain.Classes" id="ClassResultMap2">
46         <id property="id" column="c_id"/>
47         <result property="name" column="c_name"/>
48         <association property="teacher" column="teacher_id" select="getTeacher"/>
49      </resultMap>
50      
51      <select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher">
52         SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
53      </select>

 MyBatis中使用association標簽來解決一對一的關聯查詢,association標簽可用的屬性如下:

  • property:對象屬性的名稱
  • javaType:對象屬性的類型
  • column:所對應的外鍵字段名稱
  • select:使用另一個查詢封裝的結果

一對一關聯

根據班級id查詢班級信息(帶老師的信息)
10         ##1. 聯表查詢
11         SELECT * FROM class c,teacher t WHERE c.teacher_id=t.t_id AND c.c_id=1;
復制代碼
<select id="getClass" parameterType="int" resultMap="ClassResultMap">
24         select * from class c, teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
25     </select>
26     <!-- 使用resultMap映射實體類和字段之間的一一對應關系 -->
27     <resultMap type="me.gacl.domain.Classes" id="ClassResultMap">
28         <id property="id" column="c_id"/>
29         <result property="name" column="c_name"/>
30         <association property="teacher" javaType="me.gacl.domain.Teacher">
31             <id property="id" column="t_id"/>
32             <result property="name" column="t_name"/>
33         </association>
34     </resultMap>
復制代碼
<!-- 
37     方式二:嵌套查詢:通過執行另外一個SQL映射語句來返回預期的復雜類型
38         SELECT * FROM class WHERE c_id=1;
39         SELECT * FROM teacher WHERE t_id=1   //1 是上一個查詢得到的teacher_id的值
40     -->
41      <select id="getClass2" parameterType="int" resultMap="ClassResultMap2">
42         select * from class where c_id=#{id}
43      </select>
44      <!-- 使用resultMap映射實體類和字段之間的一一對應關系 -->
45      <resultMap type="me.gacl.domain.Classes" id="ClassResultMap2">
46         <id property="id" column="c_id"/>
47         <result property="name" column="c_name"/>
48         <association property="teacher" column="teacher_id" select="getTeacher"/>
49      </resultMap>
50      
51      <select id="getTeacher" parameterType="int" resultType="me.gacl.domain.Teacher">
52         SELECT t_id id, t_name name FROM teacher WHERE t_id=#{id}
53      </select>

 MyBatis中使用association標簽來解決一對一的關聯查詢,association標簽可用的屬性如下:

  • property:對象屬性的名稱
  • javaType:對象屬性的類型
  • column:所對應的外鍵字段名稱
  • select:使用另一個查詢封裝的結果

15.

2.6、MyBatis一對多關聯查詢總結

  MyBatis中使用collection標簽來解決一對多的關聯查詢,ofType屬性指定集合中元素的對象類型。

本文部分轉自http://www.cnblogs.com/xdp-gacl/p/4264440.html

16.mybatis調用存儲過程

復制代碼
三、編輯userMapper.xml

  編輯userMapper.xml文件,添加如下的配置項

復制代碼
 1 <!-- 
 2         查詢得到男性或女性的數量, 如果傳入的是0就女性否則是男性
 3      -->
 4     <select id="getUserCount" parameterMap="getUserCountMap" statementType="CALLABLE">
 5         CALL mybatis.ges_user_count(?,?)
 6     </select>
 7     
 8     <!--
 9         parameterMap.put("sexid", 0);
10         parameterMap.put("usercount", -1);
11      -->
12     <parameterMap type="java.util.Map" id="getUserCountMap">
13         <parameter property="sexid" mode="IN" jdbcType="INTEGER"/>
14         <parameter property="usercount" mode="OUT" jdbcType="INTEGER"/>
15     </parameterMap>
復制代碼
四、編寫單元測試代碼

復制代碼
 1 package me.gacl.test;
 2 
 3 import java.util.HashMap;
 4 import java.util.List;
 5 import java.util.Map;
 6 
 7 import me.gacl.custom.model.ConditionUser;
 8 import me.gacl.domain.User;
 9 import me.gacl.util.MyBatisUtil;
10 import org.apache.ibatis.session.SqlSession;
11 import org.junit.Test;
12 
13 /**
14  * @author gacl
15  * 測試調用存儲過程
16  */
17 public class Test6 {
18     
19     @Test
20     public void testGetUserCount(){
21         SqlSession sqlSession = MyBatisUtil.getSqlSession();
22         /**
23          * 映射sql的標識字符串,
24          * me.gacl.mapping.userMapper是userMapper.xml文件中mapper標簽的namespace屬性的值,
25          * getUserCount是select標簽的id屬性值,通過select標簽的id屬性值就可以找到要執行的SQL
26          */
27         String statement = "me.gacl.mapping.userMapper.getUserCount";//映射sql的標識字符串
28         Map<String, Integer> parameterMap = new HashMap<String, Integer>();
29         parameterMap.put("sexid", 1);
30         parameterMap.put("usercount", -1);
31         sqlSession.selectOne(statement, parameterMap);
32         Integer result = parameterMap.get("usercount");
33         System.out.println(result);
34         sqlSession.close();
35     }
36 }
復制代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM