Mybatis的集成和使用

SpringBoot的集成和使用

MyBatis是一款優秀的持久層框架,它支持定製化SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis可以使用簡單的XML或註解來配置和映射原生信息,將接口和Java的POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。

這裏介紹基於xml註解兩種方式進行配置。同時使用mybatis-spring-boot-starter進行集成。

這裏選用的mybatis-spring-boot-starter版本爲:1.3.2
對應Mybatis版本爲:3.4.6

通用配置

兩種方式都引入一下的pom配置:

<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

這裏以user表爲例子,數據庫爲mysql

DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (  `id` bigint(20) DEFAULT NULL COMMENT '唯一標示',  `code` varchar(20) DEFAULT NULL COMMENT '編碼',  `name` varchar(64) DEFAULT NULL COMMENT '名稱',  `status` char(1) DEFAULT '1' COMMENT '狀態 1啓用 0 停用',  `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',  `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間') ENGINE=InnoDB DEFAULT CHARSET=utf8;

實體類User爲:

/**
 * <p>
 * 
 * </p>
 *
 * @author oKong
 * @since 2018-12-02
 */@Data
@Accessors(chain = true)public class User implements Serializable{     /**
     * 
     */
    private static final long serialVersionUID = 1779270373648636358L;    /**
     * 唯一標示
     */
    private Long id;    /**
     * 編碼
     */
    private String code;    /**
     * 名稱
     */
    private String name;    
    /**
     * 狀態1 啓用 0 停用
     */
    private StatusEnum status;    /**
     * 創建時間
     */
    private Date gmtCreate;    /**
     * 修改時間
     */
    private Date gmtModified;
}

狀態枚舉類StatusEnum

public enum StatusEnum {
    
    DISABLE,
    ENABLE;

}

配置文件:application.properties

# 實體別名mybatis.type-aliases-package=cn.lqdev.learning.springboot.chapter35.biz.entity# 數據庫配置spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/learning?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=

spring.profiles.active=anno

啓動類

/**
 * mybaits集成
 * @author oKong
 *
 */@SpringBootApplication@Slf4jpublic class MybatisApplication {    public static void main(String[] args) throws Exception {
        SpringApplication.run(MybatisApplication.class, args);
        log.info("spring-boot-mybatis-chapter35啓動!");
    }
}

註解方式

0.創建註解版的mapper:

UserMapper.java

/**
 * 註解配置
 * @author okong
 *
 */public interface UserMapper {    //配置返回的字段類型,這裏配置了創建日期和修改日期自動
    @Select("select * from user where id = #{id}")    @Results({        @Result(column = "gmt_create",property = "gmtCreate",jdbcType=JdbcType.DATE),        @Result(column = "gmt_modified",property = "gmtModified",jdbcType=JdbcType.DATE)
    })    User queryOne(Long id);    
    // 枚舉類 默認是使用 EnumTypeHandler 處理類,即使用枚舉name作爲值
    //status 爲枚舉類 也可以直接指定了 typeHandler類 作爲處理類 ,如:#{status,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}
    //還可以在sqlFactory 直接使用  TypeHandlerRegistry  進行註冊 詳看;MybatisConfig 類
    //最簡單:自定義 ConfigurationCustomizer 了進行設置 詳看;MybatisConfig 類
    @Insert("insert into user(code,name,status) values(#{code},#{name}, #{status})")    //以下配置會對user對象進行id賦值
    @Options(keyProperty="id",keyColumn="id",useGeneratedKeys=true)    int insert(User user);    
    @Update("update user set code=#{code}, name = #{name}, status = #{status} where id=#{id}")    void update(User user);    
    @Delete("delete from user where id=#{id}")    void delete(Long id);    
    @Select("select * from user where code = #{code}")    @Results({        @Result(column = "gmt_create",property = "gmtCreate",jdbcType=JdbcType.DATE),        @Result(column = "gmt_modified",property = "gmtModified",jdbcType=JdbcType.DATE)
    })    
    List<User> queryByParams(@Param("code")String code);
}

簡單對以上相關注解進行說明下:

  • @Select 是查詢類的註解,所有的查詢均使用這個

  • @Result 修飾返回的結果集,關聯實體類屬性和數據庫字段一一對應,如果實體類屬性和數據庫屬性名保持一致,就不需要這個屬性來修飾。

  • @Insert 插入數據庫使用,直接傳入實體類會自動解析屬性到對應的值

  • @Update 負責修改,也可以直接傳入對象

  • @delete 負責刪除

  • @Options 映射語句的屬性,如新增時需要返回自增的ID時:@Options(keyProperty="id",keyColumn="id",useGeneratedKeys=true)

  • 在此我向大家推薦一個架構學習交流圈:830478757  幫助突破瓶頸 提升思維能力

具體的可以去官網查閱:http://www.mybatis.org/mybatis-3/zh/java-api.html

映射器註解

2.指定mapper掃描包路徑,使用註解@MapperScan

/**
 * mybaits配置
 * @author oKong
 *
 */@Configuration@MapperScan("cn.lqdev.learning.springboot.chapter35.biz.mapper")//mapper地址public class MybatisConfig {
     
}

注意:若使用Druid進行數據連接池管理,也可以在此類中進行DataSource的相關配置。

3.編寫測試類進行測試。

/**
 * 測試類
 * @author oKong
 *
 */@RunWith(SpringRunner.class)@SpringBootTest@ActiveProfiles("anno")@Slf4jpublic class UserMapperTest {    
    @Autowired
    UserMapper userMpper;    
    @Test
    public void testInsert() {
        User user = new User();
        user.setCode("002");
        user.setName("name002");
        user.setStatus(StatusEnum.ENABLE);        
        //新增
        userMpper.insert(user);
    }    
    @Test
    public void testQueryOne() {
        User user = userMpper.queryOne(1L);
        log.info("id爲1的查詢結果爲:{}", user);
    }    
    @Test
    public void testUpdate() {
        User user = new User();
        user.setCode("002");
        user.setName("testUpdate");
        user.setStatus(StatusEnum.ENABLE);
        userMpper.insert(user);
        
        User userUpd = userMpper.queryOne(user.getId());
        userUpd.setName("更新name");
        userMpper.update(userUpd);
        
        Assert.assertEquals("更新失敗",userUpd.getName(), userMpper.queryOne(user.getId()).getName());
    }    
    @Test
    public void testParamSelect() {
        String code = "002";
        List<User> list = userMpper.queryByParams(code);
        
        log.info("查詢編碼爲002,查詢結果爲:{}條,結果集爲:{}",list.size(), Arrays.toString(list.toArray()));
    }

}

運行測試用例後,就可以看見效果了。

具體控制檯輸出就輸出了,可下載源碼自行測試下。

xml方式

0.配置xml版的mapper。

/**
 * xml映射
 * @author oKong
 *
 */public interface UserXmlMapper {    User queryOne(Long id);    
    int insert(User user);    
    void update(User user);    
    void delete(Long id);        
    List<User> queryByParams(@Param("code")String code);
}

沒啥區別,就是講sql語句放入到了xml中進行編寫而已。

1.編寫mapper.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="cn.lqdev.learning.springboot.chapter35.biz.mapper.UserXmlMapper">
   
    <!-- 配置返回類型 -->
   <resultMap type="User" id="userResultMap">
      <result column="id" property="id"/>
      <result column="code" property="code"/>
      <result column="name" property="name"/>
      <result column="status" property="status"/>
      <result column="gmt_create" property="gmtCreate" jdbcType="DATE"/>
      <result column="gmt_modified" property="gmtModified" jdbcType="DATE"/>
   
   </resultMap>

    <!-- 通用查詢結果列 -->
    <sql id="Base_Column_List">
        id, code, name, status, gmt_create, gmt_modified    </sql>
    
    <select id="queryOne" resultMap="userResultMap">
      select 
      <include refid="Base_Column_List"></include>
      from user
      where id = #{id}    </select>

    <!-- 返回主鍵id -->
    <insert id="insert" parameterType="User" keyProperty="id" useGeneratedKeys="true">
        insert into user(code,name,status) values(#{code},#{name}, #{status})        <!--  insert into user(code,name,status) values(#{code},#{name}, #{status, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}) -->
    </insert>
    
    <update id="update"  parameterType="User">
       update user set code=#{code}, name = #{name}, status = #{status} where id=#{id}    </update>
    
    <delete id="delete">
       delete from user where id=#{id}    </delete>
    
    <select id="queryByParams" resultMap="userResultMap">
      select 
      <include refid="Base_Column_List"></include>
      from user
       where code = #{code}    </select></mapper>

2.mybatis配置文件。

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>
    <!--全局配置-->
    <settings>
        <!-- 這個配置使全局的映射器啓用或禁用緩存 -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 全局啓用或禁用延遲加載。當禁用時,所有關聯對象都會即時加載 -->
        <setting name="lazyLoadingEnabled" value="false"/>
        <setting name="multipleResultSetsEnabled" value="true"/>
        <setting name="useColumnLabel" value="true"/>
        <setting name="defaultExecutorType" value="REUSE"/>
        <setting name="defaultStatementTimeout" value="25000"/>
        <setting name="aggressiveLazyLoading" value="true"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    <typeHandlers>
       <!-- 枚舉類 -->
       <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
         javaType="cn.lqdev.learning.springboot.chapter35.biz.entity.StatusEnum"/>
    </typeHandlers>
    </configuration>

對於特殊的類型,可以通過typeHandlers進行配置。稍後章節也會講解想通過其他的方式進行配置。

    在此我向大家推薦一個架構學習交流圈:830478757  幫助突破瓶頸 提升思維能力

3.創建xml方式配置文件:application-xml.properties,配置xml和config的路徑地址

# 配置mapper.xml和mybatis-config.xml路徑mybatis.config-location=classpath:mybatis/mybatis-config.xmlmybatis.mapper-locations=classpath:mybatis/mapper/*.xml

4.編寫測試類:UserXmlMapperTest.java
此類和UserMapperTest類似的,唯一區別就是制定了運行環境變量爲:xml

@ActiveProfiles("xml")

枚舉類型處理器配置

在實體對象中我們設置了枚舉類型:StatusEnum。在mybatis中對於枚舉的默認配置是由EnumTypeHandler處理類進行處理的,其會默認使用name進行賦值。同時mybatis還提供了一個EnumOrdinalTypeHandler處理類,其是根據枚舉的索引值進行賦值的。

註冊類型處理類有很多中方式,但每一種方式最後都是通過TypeHandlerRegistry類進行處理的,這裏講解下通過多種方式進行配置。

  • 配置文件中新增屬性:mybatis.type-handlers-package:配置處理類的路徑。

# 類型處理類mybatis.type-handlers-package=cn.lqdev.learning.springboot.chapter35.config

處理類示例:CustomEnumOrdinalTypeHandler.java。這裏直接繼承EnumOrdinalTypeHandler進行自定義。

/**
 * 
 * @author oKong
 *
 *///枚舉索引處理類@MappedTypes(value = { StatusEnum.class })public class CustomEnumOrdinalTypeHandler<E extends Enum<E>> extends EnumOrdinalTypeHandler<E>{    public CustomEnumOrdinalTypeHandler(Class<E> type) {        super(type);
    }
}

其中,@MapperType指定了哪些類型指定此處理類的。

  • 自定義ConfigurationCustomizer類進行配置(推薦)。

    /**
     * 
     * <p>函數名稱:  ConfigurationCustomizer      </p>
     * <p>功能說明: 自定義相關注冊器
     *
     * </p>
     *<p>參數說明:</p>
     * @return
     *
     * @date   創建時間:2018年12月2日
     * @author 作者:oKong
     */
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        ConfigurationCustomizer config = new ConfigurationCustomizer() {            
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {//                TypeAliasRegistry typeAliasRegistry = configuration.getTypeAliasRegistry();
                // mapper接口註冊器//                MapperRegistry mapperRegistry = configuration.getMapperRegistry();
                // 類型處理器
                TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
                typeHandlerRegistry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);
            }
        };        
        return config;
    }
  • 通過SqlSessionFactory來獲取TypeHandlerRegistry進行配置。

    @Autowired
    SqlSessionFactory sqlSessionFactory;    
    @PostConstruct
    public void registerTypeHandler() {
        TypeHandlerRegistry registry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
        registry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);
    }

以上三種都可以進行相關類型的處理類配置,建議直接使用第二種。

完整的MybatisConfig類:

/**
 * mybaits配置
 * @author oKong
 *
 */@Configuration@MapperScan("cn.lqdev.learning.springboot.chapter35.biz.mapper")//mapper地址public class MybatisConfig {    
    //使用 SqlSessionFactory 類獲取 TypeHandlerRegistry 進行註冊//    @Autowired//    SqlSessionFactory sqlSessionFactory;//    //    @PostConstruct//    public void registerTypeHandler() {//        TypeHandlerRegistry registry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();//        registry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);//    }
    
    /**
     * 
     * <p>函數名稱:  ConfigurationCustomizer      </p>
     * <p>功能說明: 自定義相關注冊器
     *
     * </p>
     *<p>參數說明:</p>
     * @return
     *
     * @date   創建時間:2018年12月2日
     * @author 作者:oKong
     */
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        ConfigurationCustomizer config = new ConfigurationCustomizer() {            
            @Override
            public void customize(org.apache.ibatis.session.Configuration configuration) {//                TypeAliasRegistry typeAliasRegistry = configuration.getTypeAliasRegistry();
                // mapper接口註冊器//                MapperRegistry mapperRegistry = configuration.getMapperRegistry();
                // 類型處理器
                TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
                typeHandlerRegistry.register(StatusEnum.class, EnumOrdinalTypeHandler.class);
            }
        };        
        return config;
    }
}

 

總結

本章節主要簡單介紹了mybatis集成的兩種模式。兩種模式各有特點,註解版適合簡單快速的模式,而xml方式適合相對複雜的sql語句,寫在xml中,可以進行統一修改,而不需要去修改java代碼。對於原生使用mybatis而言,感覺也是比較簡單的,就是寫起語句比較麻煩,都需要手動去編寫。對於代碼生成器,大家可執行搜索相關材料下,大致看了下有點麻煩。所以還是選擇一個腳手架吧,mybatis-plus是一個很好的選擇。當然了其他的腳手架框架了,大家可自行根據實際情況進行抉擇。前幾天去看博客評論時,有人覺得開發本來就很累了還要學習這種小框架,我覺得吧,這些小框架可以節省多少繁瑣的工作呀。讓開發人員可以專注於業務代碼,多美好的一件事情呀。大家可以直接下載源碼示例進行查看下,原本想分開兩個工程進行講解,感覺也沒有必要,就合併在一起了,通過不同的環境配置進行切換,還請諒解呀


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章