Mybatis初體驗

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

之前都是用Hibernate比較多,項目中使用到的Mybatis封裝的Dao也是別人封裝好的。今天第一次看Mybatis文檔,寫一個簡單的demo加深印象。java

Mybatis入門

開發環境配置

新建一個maven項目:
clipboard.png
加入mysql-connector-javamybatis,還有Lombok(Lombok不是必須的)的依賴:mysql

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.fengyuan</groupId>
    <artifactId>mybatis-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.14.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.8</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

建表

在mysql中新建數據庫mybatisdemo,並建立student表:
clipboard.pngsql

表中有兩條記錄:
clipboard.png數據庫

建立實體類

建立表對應的Model,Student類:apache

package com.fengyuan.domain;

import lombok.Data;

public @Data class Student {
    private int id;
    private String name;
    private int age;
}

添加配置文件

在項目中新建mybatis文件夾,在其中添加Mybatis的配置文件mybatis-conf.xml,在其中配置數據源。session

<?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="Student" type="com.fengyuan.domain.Student" />
    </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://localhost:3306/mybatisdemo" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>
</configuration>

其中,<typeAliases>標籤內指定的是你定義的實體類的別名,方便以後使用。mybatis

定義映射文件

在mybatis文件夾底下新建一個mapper文件夾,存放映射文件,在其中新建student表對應的映射文件studentMapper.xmlapp

<?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.fengyuan.domain.StudentMapper">
    <select id="getStudentById" parameterType="int" resultType="Student">
        select * from student where id=#{id}
    </select>
</mapper>

namespace是惟一的,namespace有點像包名+類名,id像是方法名。parameterType是方法的參數類型,resultType中的"Student"就是前面定義的別名,是方法的返回類型。
定義完映射文件,將其註冊到配置文件中:框架

<?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="Student" type="com.fengyuan.domain.Student" />
    </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://localhost:3306/mybatisdemo" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>

    <!--註冊映射文件-->
    <mappers>
        <mapper resource="mybatis/mapper/studentMapper.xml" />
    </mappers>
</configuration>

測試

完成以上步驟,就能夠開始測試了。
測試類:

package com.fengyuan.client;

import java.io.IOException;
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.fengyuan.domain.Student;

public class Main {
    public static void main(String[] args) {
        Reader reader = null;
        try {
            // 加載配置文件
            reader = Resources.getResourceAsReader("mybatis/mybatis-conf.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 構建SqlSession工廠,並從工廠裏打開一個SqlSession
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        
        try {
             // 找到對應的sql
            String statement = "com.fengyuan.domain.StudentMapper.getStudentById";
            // 傳入參數id=1,執行sql,返回查詢結果
            Student student = sqlSession.selectOne(statement, 1);
            System.out.println(student);
        } finally {
            sqlSession.close();
        }
    }
}

執行結果:

Student(id=1, name=Can Liu, age=40)

表中id爲1的記錄已經取出來了。

項目結構:

clipboard.png

另外一種映射方式

前面的這種映射方式,雖然能夠用,可是要用字符串來找對應的sql很不方便,還有可能出錯。mybatis提供了註解的方式,更簡單也更直觀。

定義接口

在項目中建立一個Dao接口StudentDao.java

package com.fengyuan.dao;

import org.apache.ibatis.annotations.Select;

import com.fengyuan.domain.Student;

public interface StudentDao {
    @Select("select * from student where id = #{id}")
    public Student getStudentById(int id);
}

把剛纔寫在映射文件中的sql語句寫在@Select註解中便可,這樣一來映射文件studentMappper.xml就不用了。

固然,若是要用xml來映射也是能夠的,接口中只寫方法,不要加註解。此時要求namespace必須與對應的接口全類名一致,id必須與對應接口的某個對應的方法名一致,以下:

<?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.fengyuan.dao.StudentDao">
    <select id="getStudentById" parameterType="int" resultType="Student">
        select * from student where id=#{id}
    </select>
</mapper>

註冊接口

<?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="Student" type="com.fengyuan.domain.Student" />
    </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://localhost:3306/mybatisdemo" />
                <property name="username" value="root" />
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>

    <!-- 註冊映射文件 -->
    <!-- <mappers>
        <mapper resource="mybatis/mapper/studentMapper.xml" />
    </mappers> -->
    
    <!-- 註冊接口 -->
    <mappers>
        <mapper class="com.fengyuan.dao.StudentDao" />
    </mappers>
    
</configuration>

測試

package com.fengyuan.client;

import java.io.IOException;
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.fengyuan.dao.StudentDao;
import com.fengyuan.domain.Student;

public class Main {
    public static void main(String[] args) {
        Reader reader = null;
        try {
            // 加載配置文件
            reader = Resources.getResourceAsReader("mybatis/mybatis-conf.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 構建SqlSession工廠,並從工廠裏打開一個SqlSession
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 若是配置文件中沒有註冊接口,能夠在代碼裏註冊
        //sqlSession.getConfiguration().addMapper(StudentDao.class);
        
        try {
            // 獲取映射類
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            // 直接調用接口的方法,傳入參數id=1,返回Student對象
            Student student = studentDao.getStudentById(1);
            System.out.println(student);
        } finally {
            sqlSession.close();
        }
    }
}

如代碼中的註釋,除了在配置文件中註冊接口,也能夠在代碼中用
sqlSession.getConfiguration().addMapper(StudentDao.class);來註冊。
而後就能夠直接調用接口的方法來執行對應的sql語句,比第一種方式要直觀、並且「面向對象」了不少。

此時的項目結構:
clipboard.png

CURD

除了前面演示的select語句,這邊補充一下其餘的示例。

使用註解映射

在接口studentDao.java中定義相應的方法,並在註解中寫上對應的sql:

package com.fengyuan.dao;

import java.util.List;

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 com.fengyuan.domain.Student;

public interface StudentDao {
    @Select("select * from student where id= #{id}")
    public Student getStudentById(int id);
    
    @Insert("insert into student(name, age) values(#{name}, #{age})")
    public int addStudent(Student student);
    
    @Delete("delete from student where name = #{name}")
    public int removeStudentByName(String name);
    
    @Update("update student set age = #{age} where id = #{id}")
    public int updateStudent(Student student);
    
    @Select("select * from student")
    public List<Student> listAllStudents();
}

使用XML文件映射

若是是用XML文件,接口中只要定義好方法:

package com.fengyuan.dao;

import java.util.List;

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 com.fengyuan.domain.Student;

public interface StudentDao {
    public Student getStudentById(int id);
    
    public int addStudent(Student student);
    
    public int removeStudentByName(String name);
    
    public int updateStudent(Student student);
    
    public List<Student> listAllStudents();
}

而後,在XML文件中,定義好對應的sql:

<?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.fengyuan.dao.StudentDao">
    <select id="getStudentById" parameterType="int" resultType="Student">
        select * from student where id=#{id}
    </select>
    
    <insert id="addStudent" parameterType="Student">
        insert into student(name, age) values(#{name}, #{age})
    </insert>
    
    <delete id="removeStudentByName" parameterType="String">
        delete from student where name = #{name}
    </delete>
    
    <update id="updateStudent" parameterType="Student">
        update student set age = #{age} where id = #{id}
    </update>
    
    <select id="listAllStudents" resultType="Student">
        select * from student
    </select>
</mapper>

注意namespace與id要與接口中一一對應。

註冊到配置文件中

<mappers>
    <mapper class="com.fengyuan.dao.StudentDao" />
</mappers>

或者

<mappers>
    <mapper resource="mybatis/mapper/studentMapper.xml" />
</mappers>

測試

package com.fengyuan.client;

import java.io.Reader;
import java.util.List;

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

import com.fengyuan.dao.StudentDao;
import com.fengyuan.domain.Student;

public class Main {
    private static Reader reader;
    private static SqlSessionFactory sqlSessionFactory;
    
    static {
        try {
            reader = Resources.getResourceAsReader("mybatis/mybatis-conf.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 獲取sqlSession
     * @return
     */
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
    
    /**
     * 查詢
     */
    public static void testQuery() {
        SqlSession sqlSession = getSqlSession();
        try {
            // 獲取映射類
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            
            // 根據id返回Student對象
            Student student = studentDao.getStudentById(1);
            System.out.println(student);
            
        } finally {
            sqlSession.close();
        }
    }
    
    /**
     * 新增
     */
    public static void testInsert() {
        SqlSession sqlSession = getSqlSession();
        try {
            // 獲取映射類
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            
            // 新建一個student對象
            Student student = new Student();
            student.setName("Aaron");
            student.setAge(24);
            
            // 插入到表中
            studentDao.addStudent(student);
            // 提交事務
            sqlSession.commit();
        } finally {
            sqlSession.close();
        }
    }
    
    /**
     * 更新
     */
    public static void testUpdate() {
        SqlSession sqlSession = getSqlSession();
        try {
            // 獲取映射類
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            
            // 取出student記錄,修改年齡,再更新到數據庫
            Student student = studentDao.getStudentById(2);
            student.setAge(44);
            studentDao.updateStudent(student);
            
            // 提交事務
            sqlSession.commit();
        } finally {
            sqlSession.close();
        }
    }
    
    /**
     * 刪除
     */
    public static void testRemove() {
        SqlSession sqlSession = getSqlSession();
        try {
            // 獲取映射類
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            
            studentDao.removeStudentByName("cly");
            
            // 提交事務
            sqlSession.commit();
        } finally {
            sqlSession.close();
        }
    }
    
    /**
     * 以List返回student表中全部記錄
     */
    public static void testGetAll() {
        SqlSession sqlSession = getSqlSession();
        try {
            // 獲取映射類
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            
            List<Student> students = studentDao.listAllStudents();
            System.out.println(students);
            
            // 提交事務
            sqlSession.commit();
        } finally {
            sqlSession.close();
        }
    }
    
    
    public static void main(String[] args) {
        
    }
}

Mybatis-Generator

手動書寫Mapping映射文件不只繁瑣並且容易出錯,經過Mybatis-Generator,能夠幫咱們自動生成相關的文件。如下內容是從這篇博客中學習的,感謝博主。

準備

  1. 建表
    這邊咱們仍是用前面的student表來做爲示例。

  2. mybatis-generator-core
    我這邊用的是mybatis-generator-core-1.3.2.jar

  3. 數據庫驅動
    一樣,數據庫用的是mysql,因此用了mysql-connector-java-5.1.25.jar

  4. 配置文件
    generatorConfig.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--數據庫驅動-->
    <classPathEntry    location="mysql-connector-java-5.1.25.jar"/>
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--數據庫連接地址帳號密碼-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatisdemo" userId="root" password="123456">
        </jdbcConnection>
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!--生成Model類存放位置-->
        <javaModelGenerator targetPackage="com.fengyuan.model" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!--生成映射文件存放位置-->
        <sqlMapGenerator targetPackage="com.fengyuan.mapping" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!--生成Dao類存放位置-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.fengyuan.dao" targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!--生成對應表及類名-->
        <table tableName="student" domainObjectName="Student" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
    </context>
</generatorConfiguration>

相關文件截圖:

clipboard.png

執行

在命令行執行命令:

java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite

輸出Mybatis Generator finished successfully.,表示執行成功,在指定的路徑生成了相應文件。若是有問題會輸出相應的提示。

結果

根據配置,咱們生成了三個文件。

  1. 在src/main/java中com.fengyuan.model中生成了Student.java:

    package com.fengyuan.model;
    
    public class Student {
        private Integer id;
    
        private String name;
    
        private Integer age;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name == null ? null : name.trim();
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }
  2. 在src/main/java中com.fengyuan.mapping中生成了StudentMapper.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.fengyuan.dao.StudentMapper" >
      <resultMap id="BaseResultMap" type="com.fengyuan.model.Student" >
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="name" property="name" jdbcType="VARCHAR" />
    <result column="age" property="age" jdbcType="INTEGER" />
      </resultMap>
      <sql id="Base_Column_List" >
    id, name, age
      </sql>
      <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
    select 
    <include refid="Base_Column_List" />
    from student
    where id = #{id,jdbcType=INTEGER}
      </select>
      <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
    delete from student
    where id = #{id,jdbcType=INTEGER}
      </delete>
      <insert id="insert" parameterType="com.fengyuan.model.Student" >
    insert into student (id, name, age
      )
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER}
      )
      </insert>
      <insert id="insertSelective" parameterType="com.fengyuan.model.Student" >
    insert into student
    <trim prefix="(" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        id,
      </if>
      <if test="name != null" >
        name,
      </if>
      <if test="age != null" >
        age,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides="," >
      <if test="id != null" >
        #{id,jdbcType=INTEGER},
      </if>
      <if test="name != null" >
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null" >
        #{age,jdbcType=INTEGER},
      </if>
    </trim>
      </insert>
      <update id="updateByPrimaryKeySelective" parameterType="com.fengyuan.model.Student" >
    update student
    <set >
      <if test="name != null" >
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="age != null" >
        age = #{age,jdbcType=INTEGER},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
      </update>
      <update id="updateByPrimaryKey" parameterType="com.fengyuan.model.Student" >
    update student
    set name = #{name,jdbcType=VARCHAR},
      age = #{age,jdbcType=INTEGER}
    where id = #{id,jdbcType=INTEGER}
      </update>
    </mapper>
  3. 在src/main/java中com.fengyuan.dao中生成了StudentMapper.java:

    package com.fengyuan.dao;
    
    import com.fengyuan.model.Student;
    
    public interface StudentMapper {
        int deleteByPrimaryKey(Integer id);
    
        int insert(Student record);
    
        int insertSelective(Student record);
    
        Student selectByPrimaryKey(Integer id);
    
        int updateByPrimaryKeySelective(Student record);
    
        int updateByPrimaryKey(Student record);
    }
相關文章
相關標籤/搜索