MyBatis使用总结

一、 简介:

MyBatis 是一个简化和实现了 Java 数据持久化层(persistence layer)的开源框架,它抽象了大量的 JDBC 冗余代码,并提供了一个简单易用的 API 和数据库交互。

Java 应用程序中,数据持久化层涉及到的工作有:将从数据库查询到的数据生成所需要的 Java 对象;将 Java 对象中的数据通过 SQL 持久化到数据库中。MyBatis 通过抽象底层的 JDBC 代码,自动化 SQL 结果集产生 Java 对象、 Java 对象的数据持久化数据库中的过程使得对 SQL 的使用变得容易。

二、 基本使用:

1、 定义SQL Mapper映射配置文件:

<select id="findStudentById" parameterType="int" resultType="Student">
    SELECT STUD_ID AS studId, NAME, EMAIL FROM STUDENTS WHERE STUD_ID=#{Id}
</select>

<insert id="insertStudent" parameterType="Student">
    INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL) VALUES(#{studId},#{name},#{email})
</insert>

2、 创建接口:

public interface StudentMapper
{
    Student findStudentById(Integer id);
    void insertStudent(Student student);
}

3、 创建配置文件:

创建 MyBatis 的主要配置文件 mybatis-config.xml,其中包括数据库连接信息,类型别名等等,然后将其加到 classpath 中;

<?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.mybatis3.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/test" />
                <property name="username" value="root" />
                <property name="password" value="admin" />
            </dataSource>
        /environment>
    </environments>
    <mappers>
        <mapper resource="com/mybatis3/mappers/StudentMapper.xml" />
    </mappers>
</configuration>

4、 新建MyBatisSqlSessionFactory类:

SqlSessionFactory会话工厂,生产SqlSession会话,使用时建议使用单例模式。Sqlsession会话,SqlSession是一个接口,此接口面向用户的,用户使用接口可以操作数据(增、删、改、查)SqlSession存在多线程访问,由SqlSession不是线程安全,SqlSession使用范围建议在方法中使用。

public class MyBatisSqlSessionFactory
{
    private static SqlSessionFactory sqlSessionFactory;
    
    public static SqlSessionFactory getSqlSessionFactory() {
        if(sqlSessionFactory == null) {             
            try {
                InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                throw new RuntimeException(e.getCause());
            }
        }
        return sqlSessionFactory;
    }
    
    public static SqlSession openSession() {
        return getSqlSessionFactory().openSession();
    }
}

5、 定义POJO类:

public class Student
{
    private Integer studId;
    private String name;
    private String email;
    private Date dob;
}

6、 操作数据库:

SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
return studentMapper.findAllStudents();

三、 MyBatis缓存: 

一级缓存:

MyBatis 对通过映射的SELECT语句加载的查询结果提供了内建的缓存支持。默认情况下,启用一级缓存;即,如果你使用同一个 SqlSession接口对象调用了相同的 SELECT 语句,则直接会从缓存中返回结果,而不是再查询一次数据库。

二级缓存:

SQL 映射器 XML 配置文件中使用<cache />元素添加全局二级缓存。 此时所有的在映射语句文件定义的<select>语句的查询结果都会被缓存,所有的在映射语句文件定义的<insert>,<update> <delete>语句将会刷新缓存。

 

通过复写默认属性来自定义缓存的行为,如下:

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> 

可以为任意特定的映射语句复写默认的 cache 行为;例如,对一个 select 语句不使用缓存,可以设置useCache=false”;如下: 

<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>

四、 ResultMap 

ResultMaps 被用来 将 SQL SELECT 语句的结果集映射到 JavaBeans的属性中。我们可以定义结果集映射 ResultMaps并且在一些 SELECT 语句上引用 resultMap

1、 基本ResultMap

使用例子如下:

<resultMap id="StudentResult" type="com.mybatis3.domain.Student">
    <id property="studId" column="stud_id" />
    <result property="name" column="name" />
    <result property="email" column="email" />
    <result property="phone" column="phone" />
</resultMap>

<select id="findAllStudents" resultMap="StudentResult">
    SELECT * FROM STUDENTS
</select>

<select id="findStudentById" parameterType="int" resultMap="StudentResult">
    SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}
</select>

2、 Map类型ResultMap

<select id="findStudentById" parameterType="int" resultType="map">
    SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}
</select>

 在上述的<select>语句中,我们将 resultType 配置成 map,即 java.util.HashMap 的别名。在这种情况下,结果集的列名将会作为 Map 中的 key 值,而列值将作为 Map value 值。

3、 扩展ResultMap

ResultMap可以继承,如:

<resultMap type="Student" id="StudentResult">
    <id property="studId" column="stud_id" />
    <result property="name" column="name" />
    <result property="email" column="email" />
    <result property="phone" column="phone" />
</resultMap>

<resultMap type="Student" id="StudentWithAddressResult" extends="StudentResult">
    <result property="address.addrId" column="addr_id" />
    <result property="address.street" column="street" />
    <result property="address.city" column="city" />
    <result property="address.state" column="state" />
    <result property="address.zip" column="zip" />
    <result property="address.country" column="country" />
</resultMap>

ResultMap还可以嵌套,如:

<resultMap type="Address" id="AddressResult">
    <id property="addrId" column="addr_id" />
    <result property="street" column="street" />
    <result property="city" column="city" />
    <result property="state" column="state" />
    <result property="zip" column="zip" />
    <result property="country" column="country" />
</resultMap>
<resultMap type="Student" id="StudentWithAddressResult">
    <id property="studId" column="stud_id" />
    <result property="name" column="name" />
    <result property="email" column="email" />
    <association property="address" resultMap="AddressResult" />
</resultMap>

也可以使用<association 定义内联的 resultMap,如:

<resultMap type="Student" id="StudentWithAddressResult">
    <id property="studId" column="stud_id" />
    <result property="name" column="name" />
    <result property="email" column="email" />
    <association property="address" javaType="Address">
        <id property="addrId" column="addr_id" />
        <result property="street" column="street" />
        <result property="city" column="city" />
        <result property="state" column="state" />
        <result property="zip" column="zip" />
        <result property="country" column="country" />
    </association>
</resultMap>

 

五、 动态SQL 

1. IF条件:

<if>元素被用来有条件地嵌入 SQL 片段,如果测试条件被赋值为 true,则相应地 SQL 片段将会被添加到 SQL 语句中。 如下:

<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult"></select> 
    SELECT * FROM COURSES 
        WHERE TUTOR_ID= #{tutorId} 
    <if test="courseName != null"> 
    AND NAME LIKE #{courseName} 
    </if> 
    <if test="startDate != null"> 
    AND START_DATE >= #{startDate} 
    </if> 
    <if test="endDate != null"> 
    AND END_DATE <= #{endDate} 
    </if> 
</select> 

 

2. Choosewhenotherwise条件:

<choose>条件可以根据查询条件生成不同的SQL查询语句,如下:

<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult"> 
    SELECT * FROM COURSES 
    <choose> 
        <when test="searchBy == 'Tutor'"> 
            WHERE TUTOR_ID= #{tutorId} 
        </when> 
        <when test="searchBy == 'CourseName'"> 
            WHERE name like #{courseName} 
        </when> 
        <otherwise> 
            WHERE TUTOR start_date >= now() 
        </otherwise> 
    </choose> 
</select>

 

3. Where条件:

在需要使用至少一种查询条件的情况下, 我们应该使用WHERE子句。并且, 如果有多个条件,我们需要在条件中添加 AND ORMyBatis 提供了<where>元素支持这种类型的动态SQL语句。 如下:

<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult"> 
    SELECT * FROM COURSES 
    <where>  
        <if test=" tutorId != null "> 
            TUTOR_ID= #{tutorId} 
        </if> 
        <if test="courseName != null"> 
            AND name like #{courseName} 
        </if> 
        <if test="startDate != null"> 
            AND start_date >= #{startDate} 
        </if> 
        <if test="endDate != null"> 
            AND end_date <= #{endDate} 
        </if> 
    </where> 
</select> 

 

<where>元素只有在其内部标签有返回内容时才会在动态语句上插入 WHERE 条件语句。并且,如果 WHERE 子句以AND或者 OR打头,则打头的AND OR将会被移除。 

4. Trim条件:

<trim>元素和<where>元素类似,但是<trim>提供了在添加前缀/后缀 或者 移除前缀/后缀方面提供更大的灵活性。

 

<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult"> 
    SELECT * FROM COURSES 
    <trim prefix="WHERE" prefixOverrides="AND | OR"> 
        <if test=" tutorId != null "> 
            TUTOR_ID= #{tutorId} 
        </if> 
        <if test="courseName != null"> 
            AND name like #{courseName} 
        </if> 
    </trim> 
</select>

 

 

这里如果任意一个<if>条件为true<trim>元素会插入 WHERE,并且移除紧跟WHERE 后面的AND OR  

5. Foreach循环:

<foreach>条件可以迭代遍历一个数组或者列表,构造AND/OR条件或

一个IN子句。

<select id="searchCoursesByTutors" parameterType="map" resultMap="CourseResult"> 
    SELECT * FROM COURSES 
    <if test="tutorIds != null"> 
        <where> 
            <foreach item="tutorId" collection="tutorIds"> 
                OR tutor_id=#{tutorId} 
            </foreach> 
        </where>  
    </if>  
</select> 

 

<select id="searchCoursesByTutors" parameterType="map" resultMap="CourseResult"> 
    SELECT * FROM COURSES 
    <if test="tutorIds != null"> 
        <where> 
        tutor_id IN 
            <foreach item="tutorId" collection="tutorIds" open="(" separator="," close=")"> 
                #{tutorId} 
            </foreach> 
        </where> 
    </if> 
</select>

 

6. Set条件:

<set>元素和<where>元素类似,如果其内部条件判断有任何内容返回时,他会插入SET SQL片段。  如下:

<update id="updateStudent" parameterType="Student"> 
    update students  
    <set> 
    <if test="name != null">name=#{name},</if> 
    <if test="email != null">email=#{email},</if> 
    <if test="phone != null">phone=#{phone},</if> 
    </set> 
    where stud_id=#{id} 
</update> 

 

六、 Spring中集成MyBatis

1. 配置MyBatis Beans

applicationContext.xml中配置让 Spring 来实例化 MyBatis 组件如 SqlSessionFactorySqlSession、以及映射器 Mapper 对象:

<beans> 
  <bean id="dataSource" class="org.springframework.jdbc.datasource. DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost:3306/elearning" /> 
    <property name="username" value="root" /> 
    <property name="password" value="admin" /> 
  </bean> 
  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="typeAliases" value="com.mybatis3.domain.Student, com.mybatis3.domain.Tutor" />
    <property name="typeAliasesPackage" value="com.mybatis3.domain" /> 
    <property name="typeHandlers" value="com.mybatis3.typehandlers.PhoneTypeHandler" /> 
    <property name="typeHandlersPackage" value="com.mybatis3.typehandlers" /> 
    <property name="mapperLocations" value="classpath*:com/mybatis3/**/*.xml" /> 
    <property name="configLocation" value="WEB-INF/mybatisconfig.xml" /> 
  </bean> 
</beans>

 

2. Mapper Scan

<mybatis:scan>元素将在特定的以逗号分隔的包名列表中搜索映射器 Mapper 接口。

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://mybatis.org/schema/mybatis-spring  
        http://mybatis.org/schema/mybatis-spring.xsd"> 
    <mybatis:scan base-package="com.mybatis3.mappers" /> 
</beans>

 

3. 事务管理:

  • 配置 TransactionManager bean 实体对象:
<bean id="transactionManager"  
    class="org.springframework.jdbc. datasource.DataSourceTransactionManager"> 
  <property name="dataSource" ref="dataSource" /> 
</bean>

 

  •  Spring中使用基于注解的事务管理特性:
<tx:annotation-driven transaction-manager="transactionManager"/>

 

  •  使用事务:

可以在Spring service bean 上使用@Transactional 注解,表示在此service 中的每一个方法都应该在一个事务中运行。如果方法成功运行完毕,Spring 会提交操作。如果有运行期异常发生,则会执行回滚操作。

@Service 
@Transactional 
public class StudentService 
{ 
    @Autowired 
    private StudentMapper studentMapper; 
    public Student createStudent(Student student) 
    { 
        studentMapper.insertAddress(student.getAddress()); 
        if(student.getName().equalsIgnoreCase("")) 
        { 
            throw new RuntimeException("Student name should not be 
                                       empty."); 
        } 
        studentMapper.insertStudent(student); 
        return student; 
    } 
} 

 

posted on 2018-03-27 11:27  小夏coding  阅读(315)  评论(0编辑  收藏  举报

导航