mybatis完美的實戰教程

文件夾(?java

)[-]mysql



(讀者注:事實上這個應該叫作很是基礎的入門一下下,假設你看過Hibernate了那這個就很是的簡單)web

文章來源:http://blog.csdn.net/techbirds_bao/article/details/9233599/
spring

寫在這個系列前面的話:sql

之前之前用過ibatis,這是mybatis的前身。當時在作項目時。感受很是不錯,比hibernate靈活。

性能也比hibernate好。數據庫

而且也比較輕量級。因爲當時在項目中,沒來的及作很是很是多筆記。後來項目結束了,我也沒寫總結文檔。已通過去很久了。apache

但近期忽然又對這個ORM 工具感興趣。因爲接下來本身的項目中很是有可能採用這個ORM工具。因此在此又一次溫習了一下 mybatis, 所以就有了這個系列的 mybatis 教程.

什麼是mybatis
MyBatis是支持普通SQL查詢,存儲過程和高級映射的優秀持久層框架。編程

MyBatis消除了差點兒所有的JDBC代碼和參數的手工設置以及結果集的檢索。api

MyBatis使用簡單的XML或註解用於配置和原始映射,將接口和Java的POJOs(Plan Old Java Objects,普通的Java對象)映射成數據庫中的記錄.

orm工具的基本思想
不論是用過的hibernate,mybatis,你都可以法相他們有一個共同點:
1. 從配置文件(通常是XML配置文件裏)獲得 sessionfactory.
2. 由sessionfactory  產生 session
3. 在session 中完畢對數據的增刪改查和事務提交等.
4. 在用完以後關閉session 。數組


5. 在java 對象和 數據庫之間有作mapping 的配置文件。也通常是xml 文件。

mybatis實戰教程(mybatis in action)之中的一個:開發環境搭建

mybatis 的開發環境搭建,選擇: eclipse j2ee 版本號,mysql 5.1 ,jdk 1.7,mybatis3.2.0.jar包。這些軟件工具均可以到各自的官方站點上下載。
首先創建一個名字爲 MyBaits 的 dynamic web project 
1. 現階段,你可以直接創建java project。但通常都是開發web項目。這個系列教程最後也是web的,因此一開始就創建webproject。


2. 將 mybatis-3.2.0-SNAPSHOT.jar。mysql-connector-java-5.1.22-bin.jar 複製到 webproject的lib文件夾.
3. 建立mysql 測試數據庫和用戶表,注意。這裏採用的是 utf-8 編碼

建立用戶表,並插入一條測試數據

程序代碼 程序代碼

Create TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userName` varchar(50) DEFAULT NULL,
  `userAge` int(11) DEFAULT NULL,
  `userAddress` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;


Insert INTO `user` VALUES ('1', 'summer', '100', 'shanghai,pudong');

到此爲止,前期準備工做就完畢了。如下開始真正配置mybatis項目了。


1. 在MyBatis 裏面建立兩個源代碼文件夾,分別爲 src_user,test_src, 用例如如下方式創建,鼠標右鍵點擊 JavaResource.


2. 設置mybatis 配置文件:Configuration.xml, 在src_user文件夾下創建此文件,內容例如如下:

程序代碼 程序代碼

< ?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 alias="User" type="com.yihaomen.mybatis.model.User"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
        <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
            <property name="username" value="root"/>
            <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
   
    <mappers>
        <mapper resource="com/yihaomen/mybatis/model/User.xml"/>
    </mappers>
< /configuration>



3. 創建與數據庫相應的 java class,以及映射文件.
在src_user下創建package:com.yihaomen.mybatis.model ,並在這個 package 下創建 User 類:
程序代碼 程序代碼

package com.yihaomen.mybatis.model;

public class User {
   
    private int id;
    private String userName;
    private String userAge;
    private String userAddress;
   
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getUserAge() {
        return userAge;
    }
    public void setUserAge(String userAge) {
        this.userAge = userAge;
    }
    public String getUserAddress() {
        return userAddress;
    }
    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

}


同一時候創建這個User 的映射文件 User.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.yihaomen.mybatis.models.UserMapper">
    <select id="selectUserByID" parameterType="int" resultType="User">
        select * from `user` where id = #{id}
    </select>
< /mapper>



如下對這幾個配置文件解釋下:
1.Configuration.xml 是 mybatis 用來創建 sessionFactory 用的。裏面主要包括了數據庫鏈接相關東西,還有 java 類所相應的別名,比方 <typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/> 這個別名很重要,你在 詳細的類的映射中,比方User.xml 中 resultType 就是相應這裏的。

要保持一致,固然這裏的 resultType 還有另外單獨的定義方式,後面再說。


2.  Configuration.xml 裏面 的<mapper resource="com/yihaomen/mybatis/model/User.xml"/>是包括要映射的類的xml配置文件。
3. 在User.xml 文件中面 主要是定義各類SQL 語句,以及這些語句的參數。以及要返回的類型等.

開始測試
在test_src 源代碼文件夾下創建com.yihaomen.test這個package,並創建測試類Test:

程序代碼 程序代碼

package com.yihaomen.test;

import java.io.Reader;

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 com.yihaomen.mybatis.model.User;

public class Test {
    private static SqlSessionFactory sqlSessionFactory;
    private static Reader reader;

    static{
        try{
            reader    = Resources.getResourceAsReader("Configuration.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public static SqlSessionFactory getSession(){
        return sqlSessionFactory;
    }
   
    public static void main(String[] args) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
        User user = (User) session.selectOne("com.yihaomen.mybatis.models.UserMapper.selectUserByID", 1);
        System.out.println(user.getUserAddress());
        System.out.println(user.getUserName());
        } finally {
        session.close();
        }
    }
}

現在執行這個程序,是否是獲得查詢結果了。恭喜你,環境搭建配置成功,接下來第二章。將講述基於接口的操做方式。增刪改查。


整個project文件夾結構例如如下:




除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!


mybatis實戰教程(mybatis in action)之二:以接口的方式編程


前面一章,已經搭建好了eclipse,mybatis,mysql的環境,並且實現了一個簡單的查詢。請注意,這樣的方式是用SqlSession實例來直接運行已映射的SQL語句:
session.selectOne("com.yihaomen.mybatis.models.UserMapper.selectUserByID", 1)
事實上還有更簡單的方法,而且是更好的方法,使用合理描寫敘述參數和SQL語句返回值的接口(比方IUserOperation.class)。這樣現在就可以至此那個更簡單,更安全的代碼。沒有easy發生的字符串文字和轉換的錯誤.如下是具體過程:

在src_user源代碼文件夾下創建 com.yihaomen.mybatis.inter 這個包,並創建接口類 IUserOperation , 內容例如如下:
程序代碼 程序代碼

package com.yihaomen.mybatis.inter;
import com.yihaomen.mybatis.model.User;

public interface IUserOperation {   
    public User selectUserByID(int id);
   
}

請注意,這裏面有一個方法名 selectUserByID 必須與 User.xml 裏面配置的 select 的id 相應(<select id="selectUserByID")

重寫測試代碼
程序代碼 程序代碼

public static void main(String[] args) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            IUserOperation userOperation=session.getMapper(IUserOperation.class);
            User user = userOperation.selectUserByID(1);
            System.out.println(user.getUserAddress());
            System.out.println(user.getUserName());
        } finally {
            session.close();
        }
    }

整個project結構圖現在例如如下:


執行這個測試程序。就可以看到結果了。





除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!


mybatis實戰教程(mybatis in action)之三:實現數據的增刪改查


前面已經講到用接口的方式編程。這樣的方式,要注意的一個地方就是。在User.xml  的配置文件裏,mapper namespace="com.yihaomen.mybatis.inter.IUserOperation" ,命名空間很重要,不能有錯,必須與咱們定義的package 和 接口一致。

假設不一致就會出錯,這一章主要在上一講基於接口編程的基礎上完畢例如如下事情:
1. 用 mybatis 查詢數據,包含列表
2. 用 mybatis 添加數據
3. 用 mybatis 更新數據.
4. 用 mybatis 刪除數據.

查詢數據。前面已經講過簡單的。主要看查詢出列表的
查詢出列表。也就是返回list, 在咱們這個樣例中也就是 List<User> , 這樣的方式返回數據。需要在User.xml 裏面配置返回的類型 resultMap, 注意不是 resultType, 而這個resultMap 所相應的應該是咱們本身配置的

程序代碼 程序代碼

< !-- 爲了返回list 類型而定義的returnMap -->
    <resultMap type="User" id="resultListUser">
        <id column="id" property="id" />
        <result column="userName" property="userName" />
        <result column="userAge" property="userAge" />
        <result column="userAddress" property="userAddress" />
    </resultMap>

查詢列表的語句在 User.xml 中
程序代碼 程序代碼

< !-- 返回list 的select 語句,注意 resultMap 的值是指向前面定義好的 -->
    <select id="selectUsers" parameterType="string" resultMap="resultListUser">
        select * from user where userName like #{userName}
    </select>


在 IUserOperation 接口中添加方法:public List<User> selectUsers(String userName);   
現在在 Test 類中作測試
程序代碼 程序代碼

public void getUserList(String userName){
        SqlSession session = sqlSessionFactory.openSession();
        try {
            IUserOperation userOperation=session.getMapper(IUserOperation.class);          
            List<User> users = userOperation.selectUsers(userName);
            for(User user:users){
                System.out.println(user.getId()+":"+user.getUserName()+":"+user.getUserAddress());
            }
           
        } finally {
            session.close();
        }
    }

現在在main  方法中可以測試:
程序代碼 程序代碼

public static void main(String[] args) {
        Test testUser=new Test();
        testUser.getUserList("%");
    }

可以看到,結果成功查詢出來。

假設是查詢單個數據的話,用第二講用過的方法就可以了。

用mybatis 添加數據
在 IUserOperation 接口中添加方法:public void addUser(User user);
在 User.xml 中配置

程序代碼 程序代碼

< !--運行添加操做的SQL語句。id和parameterType 
       分別與IUserOperation接口中的addUser方法的名字和 
       參數類型一致。

以#{name}的形式引用Student參數 
       的name屬性,MyBatis將使用反射讀取Student參數 
       的此屬性。#{name}中name大寫和小寫敏感。

引用其它 
       的gender等屬性與此一致。seGeneratedKeys設置 
       爲"true"代表要MyBatis獲取由數據庫本身主動生成的主 
       鍵;keyProperty="id"指定把獲取到的主鍵值注入 
       到Student的id屬性-->
    <insert id="addUser" parameterType="User"
        useGeneratedKeys="true" keyProperty="id">
        insert into user(userName,userAge,userAddress) 
             values(#{userName},#{userAge},#{userAddress}) 
    </insert>


而後在 Test 中寫測試方法:
程序代碼 程序代碼

/**
     * 測試添加,添加後,必須提交事務。不然不會寫入到數據庫.
     */
    public void addUser(){
        User user=new User();
        user.setUserAddress("人民廣場");
        user.setUserName("飛鳥");
        user.setUserAge(80);
        SqlSession session = sqlSessionFactory.openSession();
        try {
            IUserOperation userOperation=session.getMapper(IUserOperation.class);
            userOperation.addUser(user);
            session.commit();
            System.out.println("當前添加的用戶 id爲:"+user.getId());
        } finally {
            session.close();
        }
    }


用mybatis 更新數據
方法相似,先在 IUserOperation 中添加方法:public void addUser(User user);
而後配置 User.xml
程序代碼 程序代碼

<update id="updateUser" parameterType="User" >
        update user set userName=#{userName},userAge=#{userAge},userAddress=#{userAddress} where id=#{id}
    </update>

Test 類總的測試方法例如如下:
程序代碼 程序代碼

public void updateUser(){
        //先獲得用戶,而後改動,提交。


        SqlSession session = sqlSessionFactory.openSession();
        try {
            IUserOperation userOperation=session.getMapper(IUserOperation.class);
            User user = userOperation.selectUserByID(4);           
            user.setUserAddress("原來是魔都的浦東創新園區");
            userOperation.updateUser(user);
            session.commit();
           
        } finally {
            session.close();
        }
    }



用mybatis 刪除數據
同理。IUserOperation 添加方法:public void deleteUser(int id);
配置User.xml
程序代碼 程序代碼

<delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>

而後在Test類中寫測試方法:
程序代碼 程序代碼


    /**
     * 刪除數據,刪除必定要 commit.
     * @param id
     */
    public void deleteUser(int id){
        SqlSession session = sqlSessionFactory.openSession();
        try {
            IUserOperation userOperation=session.getMapper(IUserOperation.class);          
            userOperation.deleteUser(id);
            session.commit();           
        } finally {
            session.close();
        }
    }


這樣,所有增刪改查都完畢了。注意在添加,更改,刪除的時候要調用session.commit(),這樣纔會真正對數據庫進行操做,不然是沒有提交的。



到此爲止,簡單的單表操做,應該都會了。接下來的時間了,我會講多表聯合查詢,以及結果集的選取。




除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!

mybatis實戰教程(mybatis in action)之四:實現關聯數據的查詢


有了前面幾章的基礎,對一些簡單的應用是可以處理的,但在實際項目中,經常是關聯表的查詢。比方最多見到的多對一,一對多等。這些查詢是怎樣處理的呢。這一講就講這個問題。咱們首先建立一個Article 這個表,並初始化數據.
程序代碼 程序代碼

Drop TABLE IF EXISTS `article`;
Create TABLE `article` (
  `id` int(11) NOT NULL auto_increment,
  `userid` int(11) NOT NULL,
  `title` varchar(100) NOT NULL,
  `content` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- 加入幾條測試數據
-- ----------------------------
Insert INTO `article` VALUES ('1', '1', 'test_title', 'test_content');
Insert INTO `article` VALUES ('2', '1', 'test_title_2', 'test_content_2');
Insert INTO `article` VALUES ('3', '1', 'test_title_3', 'test_content_3');
Insert INTO `article` VALUES ('4', '1', 'test_title_4', 'test_content_4');

你應該發現了,這幾個文章相應的userid都是1,因此需要用戶表user裏面有id=1的數據。可以改動成知足本身條件的數據.依照orm的規則。表已經建立了,那麼確定需要一個對象與之相應,因此咱們添加一個 Article 的class
程序代碼 程序代碼

package com.yihaomen.mybatis.model;

public class Article {
   
    private int id;
    private User user;
    private String title;
    private String content;
   
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
   
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }

}


注意一下,文章的用戶是怎麼定義的,是直接定義的一個User對象。而不是int類型。



多對一的實現
場景:在讀取某個用戶發表的所有文章。

固然仍是需要在User.xml 裏面配置 select 語句, 但重點是這個 select 的resultMap 相應什麼樣的數據呢。這是重點。這裏要引入 association 看定義例如如下:

程序代碼 程序代碼

< !-- User 聯合文章進行查詢 方法之中的一個的配置 (多對一的方式)  -->   
    <resultMap id="resultUserArticleList" type="Article">
        <id property="id" column="aid" />
        <result property="title" column="title" />
        <result property="content" column="content" />
       
        <association property="user" javaType="User">
            <id property="id" column="id" />
            <result property="userName" column="userName" />
            <result property="userAddress" column="userAddress" />           
        </association>       
    </resultMap>

< select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
       select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
              where user.id=article.userid and user.id=#{id}
    </select>

這樣配置以後。就可以了,將select 語句與resultMap 相應的映射結合起來看。就明確了。用association 來獲得關聯的用戶。這是多對一的狀況。因爲所有的文章都是同一個用戶的。

還有第二種處理方式。可以複用咱們前面已經定義好的 resultMap ,前面咱們定義過一個 resultListUser ,看這第二種方法怎樣實現:
程序代碼 程序代碼

<resultMap type="User" id="resultListUser">
        <id column="id" property="id" />
        <result column="userName" property="userName" />
        <result column="userAge" property="userAge" />
        <result column="userAddress" property="userAddress" />
    </resultMap>

    <!-- User 聯合文章進行查詢 方法之二的配置 (多對一的方式) -->   
    <resultMap id="resultUserArticleList-2" type="Article">
        <id property="id" column="aid" />
        <result property="title" column="title" />
        <result property="content" column="content" />       
        <association property="user" javaType="User" resultMap="resultListUser" />            
    </resultMap>
   
    <select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
       select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
              where user.id=article.userid and user.id=#{id}
    </select>

將 association  中相應的映射獨立抽取出來,可以達到複用的目的。

好了,現在在Test 類中寫測試代碼:
程序代碼 程序代碼

public void getUserArticles(int userid){
        SqlSession session = sqlSessionFactory.openSession();
        try {
            IUserOperation userOperation=session.getMapper(IUserOperation.class);          
            List<Article> articles = userOperation.getUserArticles(userid);
            for(Article article:articles){
                System.out.println(article.getTitle()+":"+article.getContent()+
                        ":做者是:"+article.getUser().getUserName()+":地址:"+
                         article.getUser().getUserAddress());
            }
        } finally {
            session.close();
        }
    }


漏掉了一點。咱們必定要在 IUserOperation 接口中。增長 select 相應的id 名稱一樣的方法:
public List<Article> getUserArticles(int id);

而後執行就可以測試。

整個程序下載:
下載文件 點擊下載此文件



除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!

mybatis實戰教程(mybatis in action)之五:與spring3集成(附源代碼)


在這一系列文章中,前面講到純粹用mybatis 鏈接數據庫,而後 進行增刪改查,以及多表聯合查詢的的樣例。但實際項目中,通常會用 spring 這個沾合劑來管理 datasource 等。充分利用spring 基於接口的編程,以及aop ,ioc 帶來的方便。

用spring 來管理 mybatis 與管理hibernate 有很是多相似的地方。今天的重點就是數據源管理以及 bean的配置。

你可以下載源代碼後,對照着看,源代碼沒有帶jar包,太大了,空間有限. 有截圖,你可以看到用到哪些jar包,源代碼在本文最後.

1. 首先對前面的project結構作一點改變,在src_user源碼目錄下創建目錄config ,並將原來的 mybatis 配置文件 Configuration.xml 移動到這個目錄中, 並在config 文家夾中創建 spring 配置文件:applicationContext.xml ,這個配置文件中最基本的配置:

程序代碼 程序代碼

< !--本演示樣例採用DBCP鏈接池,應預先把DBCP的jar包拷貝到project的lib文件夾下。 -->

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
     <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">
     <!--dataSource屬性指定要用到的鏈接池-->
     <property name="dataSource" ref="dataSource"/>
     <!--configLocation屬性指定mybatis的核心配置文件-->
     <property name="configLocation" value="config/Configuration.xml"/>
  </bean>

  <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>



[b]這裏面的重點就是 org.mybatis.spring.SqlSessionFactoryBean 與 org.mybatis.spring.mapper.MapperFactoryBean[b] 實現了 spring  的接口,併產生對象。具體可以查看 mybatis-spring 代碼。(http://code.google.com/p/mybatis/),假設只使用,固定模式。這樣配置就好。

而後寫測試程序
程序代碼 程序代碼

package com.yihaomen.test;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.yihaomen.mybatis.inter.IUserOperation;
import com.yihaomen.mybatis.model.Article;
import com.yihaomen.mybatis.model.User;


public class MybatisSprintTest {
   
    private static ApplicationContext ctx; 
   
    static
    { 
        ctx = new ClassPathXmlApplicationContext("config/applicationContext.xml"); 
    }       
     
    public static void main(String[] args) 
    { 
        IUserOperation mapper = (IUserOperation)ctx.getBean("userMapper");
        //測試id=1的用戶查詢,依據數據庫中的狀況,可以改爲你本身的.
        System.out.println("獲得用戶id=1的用戶信息");
        User user = mapper.selectUserByID(1);
        System.out.println(user.getUserAddress());
       
        //獲得文章列表測試
        System.out.println("獲得用戶id爲1的所有文章列表");
        List<Article> articles = mapper.getUserArticles(1);
       
        for(Article article:articles){
            System.out.println(article.getContent()+"--"+article.getTitle());
        }
       
    } 

   
}



執行就能夠獲得對應的結果.
project圖:

用到的jar包,例如如下圖:


源碼下載。不帶 jar  包,
下載文件點擊下載此文件



除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!

mybatis實戰教程(mybatis in action)之六:與Spring MVC 的集成


前面幾篇文章已經講到了mybatis與spring 的集成。但這個時候,所有的project還不是webproject,儘管我一直是建立的web project。今天將直接用mybatis與Spring mvc 的方式集成起來,源代碼在本文結尾處下載.主要有下面幾個方面的配置
1. web.xml 配置 spring dispatchservlet ,比方爲:mvc-dispatcher
2. mvc-dispatcher-servlet.xml 文件配置
3. spring applicationContext.XML文件配置(與數據庫相關。與mybatis sqlSessionFaction 整合,掃描所有mybatis mapper 文件等.)
4. 編寫controller 類
5. 編寫頁面代碼.
先有個大概映像,整個project圖例如如下:
[/code]

1. web.xml 配置 spring dispatchservlet ,比方爲:mvc-dispatcher
程序代碼 程序代碼

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:config/applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>
            org.springframework.web.context.ContextCleanupListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

2. 在web.xml 同文件夾下配置 mvc-dispatcher-servlet.xml 文件,這個文件名稱前面部分必須與你在web.xml裏面配置的DispatcherServlet 的servlet名字相應.其內容爲:
程序代碼 程序代碼

<beans xmlns=" http://www.springframework.org/schema/beans"
    xmlns:context=" http://www.springframework.org/schema/context"
    xmlns:mvc=" http://www.springframework.org/schema/mvc" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="com.yihaomen.controller" />
    <mvc:annotation-driven />
   
    <mvc:resources mapping="/static/**" location="/WEB-INF/static/"/> 
    <mvc:default-servlet-handler/> 
    
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

< /beans>

3. 在源代碼文件夾 config 文件夾下配置 spring 配置文件 applicationContext.xml
程序代碼 程序代碼

< !--本演示樣例採用DBCP鏈接池。應預先把DBCP的jar包拷貝到project的lib文件夾下。 -->  
    <context:property-placeholder    location="classpath:/config/database.properties" />
       
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://127.0.0.1:3306/mybatis?

characterEncoding=utf8"
        p:username="root" p:password="password"
        p:maxActive="10" p:maxIdle="10">
    </bean>
   
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
    </bean>
   
    
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
     <!--dataSource屬性指定要用到的鏈接池-->
     <property name="dataSource" ref="dataSource"/>
     <!--configLocation屬性指定mybatis的核心配置文件-->
     <property name="configLocation" value="classpath:config/Configuration.xml" />
     <!-- 所有配置的mapper文件 -->
     <property name="mapperLocations" value="classpath*:com/yihaomen/mapper/*.xml" />
  </bean>
 
  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
     <property name="basePackage" value="com.yihaomen.inter" />    
  </bean>



不知道爲何。一旦我用了 MapperScannerConfigurer 去掃描所有的mapper 接口時,數據庫配置datasource 就不能用讀取database.properties文件了。報錯: Cannot load JDBC driver class '${jdbc.driverClassName}'。網上有人說在spring 3.1.1 下用 sqlSessionFactionBean 注入可以解決,但我用 spring 3.1.3 仍是有問題。因此僅僅好把數據庫鏈接信息直接配置在了XML 文件中面。



4. 編寫 controller 層

程序代碼 程序代碼

package com.yihaomen.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.yihaomen.inter.IUserOperation;
import com.yihaomen.model.Article;

@Controller
@RequestMapping("/article")
public class UserController {
    @Autowired
    IUserOperation userMapper;

    @RequestMapping("/list")
    public ModelAndView listall(HttpServletRequest request,HttpServletResponse response){
        List<Article> articles=userMapper.getUserArticles(1);
        ModelAndView mav=new ModelAndView("list");
        mav.addObject("articles",articles);
        return mav;
    }
}

5. 頁面文件:
[code]
< c:forEach items="${articles}" var="item"> 
        ${item.id }--${item.title }--${item.content }<br />
    </c:forEach>


執行結果:


固然還有 mybatis 的Configure.xml  配置文件,與上一講的差點兒相同,惟一不一樣的就是不用再配置相似例如如下的:   <mapper resource="com/yihaomen/mapper/User.xml"/> ,所有這些都交給 在配置 sqlSessionFactory 的時候,由  <property name="mapperLocations" value="classpath*:com/yihaomen/mapper/*.xml" /> 去導入了。


   
源代碼下載:

下載文件mybatis spring3 MVC 程序下載

數據庫下載:

下載文件spring mvc 數據庫測試文件



除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!

mybatis實戰教程(mybatis in action)之七:實現mybatis分頁(源代碼下載)


上一篇文章裏已經講到了mybatis與spring MVC的集成。而且作了一個列表展現。顯示出所有article 列表,但沒實用到分頁,在實際的項目中,分頁是確定需要的。而且是物理分頁。不是內存分頁。

對於物理分頁方案,不一樣的數據庫,有不一樣的實現方法,對於mysql 來講 就是利用 limit offset,pagesize 方式來實現的。oracle 是經過rownum 來實現的。假設你熟悉相關數據庫的操做,是同樣的很是好擴展。本文以mysql 爲樣例來說述.先看一下效果圖(源碼在文章最後提供下載):

實現mybatis 物理分頁。一個最簡單的方式是,是在你的mapper的SQL語句中直接寫相似例如如下方式 :

程序代碼 程序代碼

<select id="getUserArticles" parameterType="Your_params" resultMap="resultUserArticleList">
       select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article
              where user.id=article.userid and user.id=#{id} limit #{offset},#{pagesize}
    </select>

請注意這裏的 parameterType 是你傳入的參數類,或者map ,裏面包括了offset,pagesize ,和其它你需要的參數,用這樣的方式。確定可以實現分頁。

這是簡單的一種方式。但更通用的一種方式是用 mybatis 插件的方式. 參考了網上的很是多資料 ,mybatis plugin 方面的資料。寫本身的插件.

程序代碼 程序代碼

package com.yihaomen.util;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.xml.bind.PropertyException;

import org.apache.ibatis.builder.xml.dynamic.ForEachSqlNode;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;

@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PagePlugin implements Interceptor {

    private static String dialect = "";
    private static String pageSqlId = "";

    @SuppressWarnings("unchecked")
    public Object intercept(Invocation ivk) throws Throwable {

        if (ivk.getTarget() instanceof RoutingStatementHandler) {
            RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk
                    .getTarget();
            BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper
                    .getValueByFieldName(statementHandler, "delegate");
            MappedStatement mappedStatement = (MappedStatement) ReflectHelper
                    .getValueByFieldName(delegate, "mappedStatement");

            if (mappedStatement.getId().matches(pageSqlId)) {
                BoundSql boundSql = delegate.getBoundSql();
                Object parameterObject = boundSql.getParameterObject();
                if (parameterObject == null) {
                    throw new NullPointerException("parameterObject error");
                } else {
                    Connection connection = (Connection) ivk.getArgs()[0];
                    String sql = boundSql.getSql();
                    String countSql = "select count(0) from (" + sql + ") myCount";
                    System.out.println("總數sql 語句:"+countSql);
                    PreparedStatement countStmt = connection
                            .prepareStatement(countSql);
                    BoundSql countBS = new BoundSql(
                            mappedStatement.getConfiguration(), countSql,
                            boundSql.getParameterMappings(), parameterObject);
                    setParameters(countStmt, mappedStatement, countBS,
                            parameterObject);
                    ResultSet rs = countStmt.executeQuery();
                    int count = 0;
                    if (rs.next()) {
                        count = rs.getInt(1);
                    }
                    rs.close();
                    countStmt.close();

                    PageInfo page = null;
                    if (parameterObject instanceof PageInfo) {
                        page = (PageInfo) parameterObject;
                        page.setTotalResult(count);
                    } else if(parameterObject instanceof Map){
                        Map<String, Object> map = (Map<String, Object>)parameterObject;
                        page = (PageInfo)map.get("page");
                        if(page == null)
                            page = new PageInfo();
                        page.setTotalResult(count);
                    }else {
                        Field pageField = ReflectHelper.getFieldByFieldName(
                                parameterObject, "page");
                        if (pageField != null) {
                            page = (PageInfo) ReflectHelper.getValueByFieldName(
                                    parameterObject, "page");
                            if (page == null)
                                page = new PageInfo();
                            page.setTotalResult(count);
                            ReflectHelper.setValueByFieldName(parameterObject,
                                    "page", page);
                        } else {
                            throw new NoSuchFieldException(parameterObject
                                    .getClass().getName());
                        }
                    }
                    String pageSql = generatePageSql(sql, page);
                    System.out.println("page sql:"+pageSql);
                    ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);
                }
            }
        }
        return ivk.proceed();
    }

    private void setParameters(PreparedStatement ps,
            MappedStatement mappedStatement, BoundSql boundSql,
            Object parameterObject) throws SQLException {
        ErrorContext.instance().activity("setting parameters")
                .object(mappedStatement.getParameterMap().getId());
        List<ParameterMapping> parameterMappings = boundSql
                .getParameterMappings();
        if (parameterMappings != null) {
            Configuration configuration = mappedStatement.getConfiguration();
            TypeHandlerRegistry typeHandlerRegistry = configuration
                    .getTypeHandlerRegistry();
            MetaObject metaObject = parameterObject == null ? null
                    : configuration.newMetaObject(parameterObject);
            for (int i = 0; i < parameterMappings.size(); i++) {
                ParameterMapping parameterMapping = parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    Object value;
                    String propertyName = parameterMapping.getProperty();
                    PropertyTokenizer prop = new PropertyTokenizer(propertyName);
                    if (parameterObject == null) {
                        value = null;
                    } else if (typeHandlerRegistry
                            .hasTypeHandler(parameterObject.getClass())) {
                        value = parameterObject;
                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
                        value = boundSql.getAdditionalParameter(propertyName);
                    } else if (propertyName
                            .startsWith(ForEachSqlNode.ITEM_PREFIX)
                            && boundSql.hasAdditionalParameter(prop.getName())) {
                        value = boundSql.getAdditionalParameter(prop.getName());
                        if (value != null) {
                            value = configuration.newMetaObject(value)
                                    .getValue(
                                            propertyName.substring(prop
                                                    .getName().length()));
                        }
                    } else {
                        value = metaObject == null ? null : metaObject
                                .getValue(propertyName);
                    }
                    TypeHandler typeHandler = parameterMapping.getTypeHandler();
                    if (typeHandler == null) {
                        throw new ExecutorException(
                                "There was no TypeHandler found for parameter "
                                        + propertyName + " of statement "
                                        + mappedStatement.getId());
                    }
                    typeHandler.setParameter(ps, i + 1, value,
                            parameterMapping.getJdbcType());
                }
            }
        }
    }


    private String generatePageSql(String sql, PageInfo page) {
        if (page != null && (dialect !=null || !dialect.equals(""))) {
            StringBuffer pageSql = new StringBuffer();
            if ("mysql".equals(dialect)) {
                pageSql.append(sql);
                pageSql.append(" limit " + page.getCurrentResult() + ","
                        + page.getShowCount());
            } else if ("oracle".equals(dialect)) {
                pageSql.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
                pageSql.append(sql);
                pageSql.append(")  tmp_tb where ROWNUM<=");
                pageSql.append(page.getCurrentResult() + page.getShowCount());
                pageSql.append(") where row_id>");
                pageSql.append(page.getCurrentResult());
            }
            return pageSql.toString();
        } else {
            return sql;
        }
    }

    public Object plugin(Object arg0) {
        // TODO Auto-generated method stub
        return Plugin.wrap(arg0, this);
    }

    public void setProperties(Properties p) {
        dialect = p.getProperty("dialect");
        if (dialect ==null || dialect.equals("")) {
            try {
                throw new PropertyException("dialect property is not found!");
            } catch (PropertyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        pageSqlId = p.getProperty("pageSqlId");
        if (dialect ==null || dialect.equals("")) {
            try {
                throw new PropertyException("pageSqlId property is not found!");
            } catch (PropertyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

此插件有兩個輔助類:PageInfo,ReflectHelper,你可以下載源碼參考。
寫了插件以後。固然需要在 mybatis 的配置文件Configuration.xml 裏配置這個插件
程序代碼 程序代碼
  
    <plugins>
        <plugin interceptor="com.yihaomen.util.PagePlugin">
            <property name="dialect" value="mysql" />
            <property name="pageSqlId" value=".*ListPage.*" />
        </plugin>
    </plugins>


請注意,這個插件定義了一個規則。也就是在mapper中sql語句的id 必須包括ListPage才幹被攔截。

不然將不會分頁處理.

插件寫好了,現在就可以在 spring mvc 中的controller 層中寫一個方法來測試這個分頁:

程序代碼 程序代碼

@RequestMapping("/pagelist")
    public ModelAndView pageList(HttpServletRequest request,HttpServletResponse response){
        int currentPage = request.getParameter("page")==null?1:Integer.parseInt(request.getParameter("page"));
        int pageSize = 3;
        if (currentPage<=0){
            currentPage =1;
        }
        int currentResult = (currentPage-1) * pageSize;
       
        System.out.println(request.getRequestURI());
        System.out.println(request.getQueryString());
       
        PageInfo page = new PageInfo();
        page.setShowCount(pageSize);
        page.setCurrentResult(currentResult);
        List<Article> articles=iUserOperation.selectArticleListPage(page,1);
       
        System.out.println(page);
       
        int totalCount = page.getTotalResult();
       
        int lastPage=0;
        if (totalCount % pageSize==0){
            lastPage = totalCount % pageSize;
        }
        else{
            lastPage =1+ totalCount / pageSize;
        }
       
        if (currentPage>=lastPage){
            currentPage =lastPage;
        }
       
        String pageStr = "";

        pageStr=String.format("<a href=\"%s\">上一頁</a>    <a href=\"%s\">下一頁</a>",
                        request.getRequestURI()+"?page="+(currentPage-1),request.getRequestURI()+"?page="+(currentPage+1) );


        //制定視圖,也就是list.jsp
        ModelAndView mav=new ModelAndView("list");
        mav.addObject("articles",articles);
        mav.addObject("pageStr",pageStr);
        return mav;
    }


而後執行程序。進入分頁頁面,你就可以看到結果了:


源碼下載:
下載文件點擊下載此文件
相關jar 包下載,請到下載這裏樣例中的jar
http://www.yihaomen.com/article/java/318.htm (文章最後有源碼下載,裏面有jar 包,複製到上面源碼裏面所需要的lib 文件夾下.)

另外,你還得在前面提到的數據庫artilce表裏面,多插入一些記錄,分頁效果就更好。


除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!

mybatis實戰教程(mybatis in action)之八:mybatis 動態sql語句


mybatis 的動態sql語句是基於OGNL表達式的。可以方便的在 sql 語句中實現某些邏輯. 總體說來mybatis 動態SQL 語句主要有下面幾類:
1. if 語句 (簡單的條件推斷)
2. choose (when,otherwize) ,至關於java 語言中的 switch ,與 jstl 中的choose 很是相似.
3. trim (對包括的內容加上 prefix,或者 suffix 等。前綴,後綴)
4. where (主要是用來簡化sql語句中where條件推斷的,能智能的處理 and or ,沒必要操心多餘致使語法錯誤)
5. set (主要用於更新時)
6. foreach (在實現 mybatis in 語句查詢時特別實用)
如下分別介紹這幾種處理方式

1. mybaits if 語句處理
程序代碼 程序代碼

    <select id="dynamicIfTest" parameterType="Blog" resultType="Blog">
        select * from t_blog where 1 = 1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="content != null">
            and content = #{content}
        </if>
        <if test="owner != null">
            and owner = #{owner}
        </if>
    </select>

這條語句的意思很easy,假設你提供了title參數。那麼就要知足title=#{title},相同假設你提供了Content和Owner的時候。它們也需要知足對應的條件,以後就是返回知足這些條件的所有Blog。這是很實用的一個功能,以往咱們使用其它類型框架或者直接使用JDBC的時候, 假設咱們要達到相同的選擇效果的時候,咱們就需要拼SQL語句,這是極其麻煩的。比起來,上述的動態SQL就要簡單多了

2.2. choose (when,otherwize) ,至關於java 語言中的 switch ,與 jstl 中的choose 很是相似
程序代碼 程序代碼

    <select id="dynamicChooseTest" parameterType="Blog" resultType="Blog">
        select * from t_blog where 1 = 1
        <choose>
            <when test="title != null">
                and title = #{title}
            </when>
            <when test="content != null">
                and content = #{content}
            </when>
            <otherwise>
                and owner = "owner1"
            </otherwise>
        </choose>
    </select>

when元素表示當when中的條件知足的時候就輸出當中的內容。跟JAVA中的switch效果差點兒相同的是依照條件的順序。當when中有條件知足的時候,就會跳出choose,即所有的when和otherwise條件中,僅僅有一個會輸出,當所有的我很是條件都不知足的時候就輸出otherwise中的內容。因此上述語句的意思很是easy。 當title!=null的時候就輸出and titlte = #{title}。再也不往下推斷條件,當title爲空且content!=null的時候就輸出and content = #{content},當所有條件都不知足的時候就輸出otherwise中的內容。

3.trim (對包括的內容加上 prefix,或者 suffix 等,前綴,後綴)
程序代碼 程序代碼

    <select id="dynamicTrimTest" parameterType="Blog" resultType="Blog">
        select * from t_blog
        <trim prefix="where" prefixOverrides="and |or">
            <if test="title != null">
                title = #{title}
            </if>
            <if test="content != null">
                and content = #{content}
            </if>
            <if test="owner != null">
                or owner = #{owner}
            </if>
        </trim>
    </select>

trim元素的主要功能是可以在本身包括的內容前加上某些前綴,也可以在其後加上某些後綴,與之相應的屬性是prefix和suffix。可以把包括內容的首部某些內容覆蓋。即忽略,也可以把尾部的某些內容覆蓋。相應的屬性是prefixOverrides和suffixOverrides。正因爲trim有這種功能。因此咱們也可以很easy的利用trim來取代where元素的功能

4. where (主要是用來簡化sql語句中where條件推斷的,能智能的處理 and or 條件
程序代碼 程序代碼

    <select id="dynamicWhereTest" parameterType="Blog" resultType="Blog">
        select * from t_blog
        <where>
            <if test="title != null">
                title = #{title}
            </if>
            <if test="content != null">
                and content = #{content}
            </if>
            <if test="owner != null">
                and owner = #{owner}
            </if>
        </where>
    </select>


where元素的做用是會在寫入where元素的地方輸出一個where,另一個優勢是你不需要考慮where元素裏面的條件輸出是什麼樣子的,MyBatis會智能的幫你處理,假設所有的條件都不知足那麼MyBatis就會查出所有的記錄,假設輸出後是and 開頭的,MyBatis會把第一個and忽略。固然假設是or開頭的,MyBatis也會把它忽略;此外。在where元素中你不需要考慮空格的問題,MyBatis會智能的幫你加上。像上述樣例中,假設title=null。 而content != null,那麼輸出的整個語句會是select * from t_blog where content = #{content}。而不是select * from t_blog where and content = #{content},因爲MyBatis會智能的把首個and 或 or 給忽略。

5.set (主要用於更新時)
程序代碼 程序代碼

    <update id="dynamicSetTest" parameterType="Blog">
        update t_blog
        <set>
            <if test="title != null">
                title = #{title},
            </if>
            <if test="content != null">
                content = #{content},
            </if>
            <if test="owner != null">
                owner = #{owner}
            </if>
        </set>
        where id = #{id}
    </update>

set元素主要是用在更新操做的時候,它的主要功能和where元素事實上是差點兒相同的,主要是在包括的語句前輸出一個set,而後假設包括的語句是以逗號結束的話將會把該逗號忽略,假設set包括的內容爲空的話則會出錯。有了set元素咱們就可以動態的更新那些改動了的字段

6. foreach (在實現 mybatis in 語句查詢時特別實用)
foreach的主要用在構建in條件中,它可以在SQL語句中進行迭代一個集合。

foreach元素的屬性主要有item。index。collection,open。separator,close。item表示集合中每一個元素進行迭代時的別名,index指定一個名字,用於表示在迭代過程當中,每次迭代到的位置,open表示該語句以什麼開始,separator表示在每次進行迭代之間以什麼符號做爲分隔符,close表示以什麼結束,在使用foreach的時候最關鍵的也是最easy出錯的就是collection屬性,該屬性是必須指定的。但是在不一樣狀況下。該屬性的值是不同的,主要有一下3種狀況:
假設傳入的是單參數且參數類型是一個List的時候。collection屬性值爲list
假設傳入的是單參數且參數類型是一個array數組的時候。collection的屬性值爲array
假設傳入的參數是多個的時候,咱們就需要把它們封裝成一個Map了。固然單參數也可以封裝成map。實際上假設你在傳入參數的時候,在MyBatis裏面也是會把它封裝成一個Map的。map的key就是參數名。因此這個時候collection屬性值就是傳入的List或array對象在本身封裝的map裏面的key

1.1.單參數List的類型

程序代碼 程序代碼

    <select id="dynamicForeachTest" resultType="Blog">
        select * from t_blog where id in
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>

上述collection的值爲list,相應的Mapper是這種
程序代碼 程序代碼

public List<Blog> dynamicForeachTest(List<Integer> ids); 


測試代碼
程序代碼 程序代碼

    @Test
    public void dynamicForeachTest() {
        SqlSession session = Util.getSqlSessionFactory().openSession();
        BlogMapper blogMapper = session.getMapper(BlogMapper.class);
        List<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(3);
        ids.add(6);
        List<Blog> blogs = blogMapper.dynamicForeachTest(ids);
        for (Blog blog : blogs)
            System.out.println(blog);
        session.close();
    }


2.數組類型的參數
程序代碼 程序代碼

    <select id="dynamicForeach2Test" resultType="Blog">
        select * from t_blog where id in
        <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>


相應mapper
程序代碼 程序代碼

public List<Blog> dynamicForeach2Test(int[] ids); 


3. Map 類型的參數
程序代碼 程序代碼

    <select id="dynamicForeach3Test" resultType="Blog">
        select * from t_blog where title like "%"#{title}"%" and id in
        <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>


mapper 應該是這種接口:
程序代碼 程序代碼

public List<Blog> dynamicForeach3Test(Map<String, Object> params);


經過以上方法,就能完畢通常的mybatis 的 動態SQL 語句.最常用的就是  if where foreach這幾個,必定要重點掌握.




除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!

mybatis實戰教程(mybatis in action)之九:mybatis 代碼生成工具的使用


mybatis 應用程序。需要大量的配置文件,對於一個成百上千的數據庫表來講,全然手工配置,這是一個很是恐怖的工做量. 因此mybatis 官方也推出了一個mybatis代碼生成工具的jar包. 今天花了一點時間。依照 mybatis generator 的doc 文檔參考。初步配置出了一個可以使用的版本號,我把源碼也提供下載,mybatis 代碼生成工具,主要有一下功能:
1.生成pojo 與 數據庫結構相應
2.假設有主鍵,能匹配主鍵
3.假設沒有主鍵,可以用其它字段去匹配
4.動態select,update,delete 方法
5.本身主動生成接口(也就是曾經的dao層)
6.本身主動生成sql mapper。增刪改查各類語句配置,包含動態where語句配置
7.生成Example 樣例供參考

如下介紹下具體過程

1. 建立測試project,並配置mybatis代碼生成jar包
下載地址:http://code.google.com/p/mybatis/downloads/list?can=3&q=Product%3DGenerator
mysql 驅動下載:http://dev.mysql.com/downloads/connector/j/
這些jar包,我也會包括在源碼裏面,可以在文章末尾處,下載源碼,參考。

用 eclipse 創建一個dynamic web project。


解壓下載後的 mybatis-generator-core-1.3.2-bundle.zip 文件。當中有兩個文件夾:一個文件夾是文檔文件夾docs,主要介紹這個代碼生成工具怎樣使用。還有一個是lib文件夾,裏面的內容主要是jar 包,這裏咱們需要 mybatis-generator-core-1.3.2.jar,這個 jar 包. 將它複製到咱們剛剛建立的 webproject的 WebContent/WEB-INF/lib  文件夾下.在這個文件夾下也放入 mysql 驅動jar包.因爲用 mysql  作測試的.

2.在數據庫中建立測試表
在mybatis數據庫中建立 用來測試的category表(假設沒有mybatis這個數據庫,要建立。這是基於前面這個系列文章而寫的。已經有了mybatis 這個數據庫)

程序代碼 程序代碼

Drop TABLE IF EXISTS `category`;
Create TABLE `category` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `catname` varchar(50) NOT NULL,
  `catdescription` varchar(200) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


3. 配置mybatis 代碼生成工具的配置文件 
在建立的webproject中,建立對應的package 比方 :
com.yihaomen.inter 用來存放mybatis 接口對象.
com.yihaomen.mapper用來存放sql mapper相應的映射,sql語句等.
com.yihaomen.model 用來存放與數據庫相應的model 。
在用mybatis 代碼生成工具以前,這些文件夾必須先建立好,做爲一個好的應用程序,這些文件夾的建立也是有規律的。

依據mybatis代碼生成工具文檔,需要一個配置文件,這裏命名爲:mbgConfiguration.xml 放在src 文件夾下. 配置文件內容例如如下:
程序代碼 程序代碼

< ?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:\Work\Java\eclipse\workspace\myBatisGenerator\WebContent\WEB-INF\lib\mysql-connector-java-5.1.22-bin.jar" />

  <context id="yihaomen_mysql_tables" targetRuntime="MyBatis3">
 
    <!-- 爲了防止生成的代碼中有很是多凝視,比較難看,增長如下的配置控制 -->
    <commentGenerator>
      <property name="suppressAllComments" value="true" />
      <property name="suppressDate" value="true" />
    </commentGenerator>
    <!-- 凝視控制完成 -->
 
    <!-- 數據庫鏈接 -->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver"
        connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8"
        userId="root"
        password="password">
    </jdbcConnection>

    <javaTypeResolver >
      <property name="forceBigDecimals" value="false" />
    </javaTypeResolver>
   
    <!-- 數據表相應的model 層  -->
    <javaModelGenerator targetPackage="com.yihaomen.model" targetProject="src">
      <property name="enableSubPackages" value="true" />
      <property name="trimStrings" value="true" />
    </javaModelGenerator>
   
    <!-- sql mapper 隱射配置文件 -->
    <sqlMapGenerator targetPackage="com.yihaomen.mapper"  targetProject="src">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
   
    <!-- 在ibatis2 中是dao層,但在mybatis3中,事實上就是mapper接口 -->
    <javaClientGenerator type="XMLMAPPER" targetPackage="com.yihaomen.inter"  targetProject="src">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
   
    <!-- 要對那些數據表進行生成操做。必須要有一個. -->
    <table schema="mybatis" tableName="category" domainObjectName="Category"
        enableCountByExample="false" enableUpdateByExample="false"
        enableDeleteByExample="false" enableSelectByExample="false"
        selectByExampleQueryId="false">    
    </table>

  </context>
< /generatorConfiguration>

用一個main 方法來測試是否能用mybatis 成生成剛剛建立的`category`表相應的model,sql mapper等內容.
建立一個com.yihaomen.test 的package ,並在此package 如下創建一個測試的類GenMain:
程序代碼 程序代碼

package com.yihaomen.test;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
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.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GenMain {
    public static void main(String[] args) {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        String genCfg = "/mbgConfiguration.xml";
        File configFile = new File(GenMain.class.getResource(genCfg).getFile());
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = null;
        try {
            config = cp.parseConfiguration(configFile);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XMLParserException e) {
            e.printStackTrace();
        }
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = null;
        try {
            myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        } catch (InvalidConfigurationException e) {
            e.printStackTrace();
        }
        try {
            myBatisGenerator.generate(null);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


到此爲止,eclipse項目project圖應該例如如下:


4.執行測試的main 方法,生成mybatis 相關代碼
執行GenMain類裏的main方法,並刷新 project,你會發現 各自package 文件夾下已經響應生成了相應的文件,全然符合mybatis 規則,效果圖例如如下:


5.注意事項
假設你想生成example 之類的東西。需要在<table></table>裏面去掉
程序代碼 程序代碼

enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false"
selectByExampleQueryId="false"

這部分配置。這是生成Example而用的,通常來講對項目沒實用.

另外生成的sql mapper 等。僅僅是對單表的增刪改查。假設你有多表join操做,你就可以手動配置,假設調用存儲過程,你也需要手工配置. 這時工做量已經少很是多了。



假設你想用命令行方式處理,也是可以的.

程序代碼 程序代碼

比方:
java -jar mybatis-generator-core-1.3.2.jar -mbgConfiguration.xm -overwrite

這時。要用絕對路徑才行. 另外mbgConfiguration.xml  配置文件裏targetProject 的配置也必須是絕對路徑了。



代碼下載:下載文件mybatis 代碼生成工具



除非申明,文章均爲 一號門原創,轉載請註明本文地址,謝謝!

mybatis SqlSessionDaoSupport的使用(附代碼下載)


前面的系列mybatis 文章,已經基本講到了mybatis的操做。但都是基於mapper隱射操做的。在mybatis 3中這個mapper 接口貌似充當了曾經在ibatis 2中的 DAO 層的做用。

但其實。假設有這個mapper接口不能完畢的工做。或者需要更復雜的擴展的時候,你就需要本身的DAO 層. 其實 mybatis 3 也是支持DAO 層設計的。相似於ibatis 2 .如下介紹下.

在此以前,請下載 上一篇文章提供的代碼:http://www.yihaomen.com/article/java/326.htm

首先建立一個com.yihaomen.dao的package.而後在裏面分別建立接口UserDAO,以及實現該接口的UserDAOImpl

程序代碼 程序代碼

package com.yihaomen.dao;
import java.util.List;
import com.yihaomen.model.Article;
public interface UserDAO {
    public List<Article> getUserArticles(int userid);
}


程序代碼 程序代碼

package com.yihaomen.dao;
import java.util.List;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.stereotype.Repository;
import com.yihaomen.model.Article;

@Repository
public class UserDAOImpl extends SqlSessionDaoSupport implements UserDAO {
    @Override
    public List<Article> getUserArticles(int userid) {       
        return this.getSqlSession().selectList("com.yihaomen.inter.IUserOperation.getUserArticles",userid);
    }
}


運行的SQL 語句採用了命名空間+sql 語句id的方式,後面是參數.

注意繼承了 "SqlSessionDaoSupport" 。利用方法 getSqlSession() 可以獲得 SqlSessionTemplate ,從而可以運行各類sql語句,相似於hibernatetemplate同樣,至少思路同樣.

假設與spring 3 mvc 集成要用  autowire的話,在daoimpl 類上 加上註解 「@Repository」 ,另外還需要在spring 配置文件裏增長<context:component-scan base-package="com.yihaomen.dao" /> 這樣在需要調用的地方,就可以使用autowire本身主動注入了。

固然,你也可以按通常程序的思路。建立一個service 的package, 用service 去調用 dao層,我這裏就沒有作了。因爲比較簡單。用相似的方法,也機注意本身主動注入時。也要配置 <context:component-scan base-package="com.yihaomen.service" /> 等這種。



在controller層中測試,直接調用dao層方法
在controller中增長方法:

程序代碼 程序代碼


    @Autowired
    UserDAO userDAO;

        .......

    @RequestMapping("/daolist")
    public ModelAndView listalldao(HttpServletRequest request,HttpServletResponse response){
        List<Article> articles=userDAO.getUserArticles(1);
        //制定視圖,也就是list.jsp
        ModelAndView mav=new ModelAndView("list");
        mav.addObject("articles",articles);
        return mav;
    }

這樣可以獲得相同的結果。而且知足了通常程序的設計方法.代碼結構例如如下:


完畢後,程序代碼下載.
下載文件點擊下載此文件
相關文章
相關標籤/搜索