zoukankan      html  css  js  c++  java
  • 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; 
        } 
    } 
  • 相关阅读:
    近期学习(3)
    近期学习(1)
    近期学习(2)
    今日练习
    《明朝那些事儿》
    记一次针对恶意攻击者的渗透测试
    Kali Linux使用问题记录
    MySQL floor()报错原理
    使用复合设计模式扩展持久化的CURD,Select能力
    c#/js代码命名规范及代码规范
  • 原文地址:https://www.cnblogs.com/laoxia/p/8656515.html
Copyright © 2011-2022 走看看