springboot之簡潔集成mybatis

orm框架的本質是簡化編程中操做數據庫的編碼,發展到如今基本上就剩兩家了,一個是宣稱能夠不用寫一句SQL的hibernate,一個是能夠靈活調試動態sql的mybatis,二者各有特色,在企業級系統開發中能夠根據需求靈活使用。發現一個有趣的現象:傳統企業大都喜歡使用hibernate,互聯網行業一般使用mybatis。java

hibernate特色就是全部的sql都用Java代碼來生成,不用跳出程序去寫(看)sql,有着編程的完整性,發展到最頂端就是spring data jpa這種模式了,基本上根據方法名就能夠生成對應的sql了。mysql

mybatis初期使用比較麻煩,須要各類配置文件、實體類、dao層映射關聯、還有一大推其它配置。固然mybatis也發現了這種弊端,初期開發了generator能夠根據表結果自動生產實體類、配置文件和dao層代碼,能夠減輕一部分開發量;後期也進行了大量的優化可使用註解了,自動管理dao層和配置文件等,發展到最頂端就是springboot+mybatis能夠徹底註解,不用配置文件,也能夠簡單配置輕鬆上手。git

mybatis-spring-boot-starter

官方說明:MyBatis Spring-Boot-Starter will help you use MyBatis with Spring Boot
其實就是MyBatis爲了配合使用spring boot開發出的一套解決方案。mybatis-spring-boot-starter主要有兩種解決方案,一種是使用註解,一種是簡化後的傳統方式。github

固然任何模式都須要首先引入mybatis-spring-boot-starter的pom文件web

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>1.1.1</version>
</dependency>

 

註解版(無配置文件)

 

1 添加相關maven文件

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
	<dependency>
		<groupId>org.mybatis.spring.boot</groupId>
		<artifactId>mybatis-spring-boot-starter</artifactId>
		<version>1.1.1</version>
	</dependency>
     <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
     <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
	</dependency>
</dependencies>

 

二、application.properties 添加相關配置

mybatis.type-aliases-package=com.neo.entity
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/dataBaseName?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = username 
spring.datasource.password = password

springboot會自動加載spring.datasource.*相關配置,數據源就會自動注入到sqlSessionFactory中,sqlSessionFactory會自動注入到Mapper中。spring

在啓動類中添加對mapper包掃描@MapperScansql

@SpringBootApplication
@MapperScan("com.neo.mapper")
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

或者直接在Mapper類上面添加註解@Mapper,建議使用上面那種,不然每一個mapper加個註解比較麻煩。數據庫

三、開發Mapper

public interface UserMapper {
	
	@Select("SELECT * FROM users")
	@Results({
		@Result(property = "userSex",  column = "user_sex", javaType = UserSexEnum.class),
		@Result(property = "nickName", column = "nick_name")
	})
	List<UserEntity> getAll();
	
	@Select("SELECT * FROM users WHERE id = #{id}")
	@Results({
		@Result(property = "userSex",  column = "user_sex", javaType = UserSexEnum.class),
		@Result(property = "nickName", column = "nick_name")
	})
	UserEntity getOne(Long id);

	@Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passWord}, #{userSex})")
	void insert(UserEntity user);

	@Update("UPDATE users SET userName=#{userName},nick_name=#{nickName} WHERE id =#{id}")
	void update(UserEntity user);

	@Delete("DELETE FROM users WHERE id =#{id}")
	void delete(Long id);

}

 

註解以下表所示:                                                                                                                                                      編程

註解 使用對象 相對應的 XML 描述
@CacheNamespace <cache> 爲給定的命名空間(好比類)配置緩存。屬性有:implemetation, eviction, flushInterval, size, readWrite, blocking 和properties。
@Property N/A <property> 指定參數值或佔位值(placeholder)(能被 mybatis-config.xml內的配置屬性覆蓋)。屬性有:name, value。(僅在MyBatis 3.4.2以上版本生效)
@CacheNamespaceRef <cacheRef> 參照另一個命名空間的緩存來使用。屬性有:value, name。若是你使用了這個註解,你應設置 value 或者 name 屬性的其中一個。value 屬性用於指定 Java 類型而指定命名空間(命名空間名就是指定的 Java 類型的全限定名),name 屬性(這個屬性僅在MyBatis 3.4.2以上版本生效)直接指定了命名空間的名字。
@ConstructorArgs 方法 <constructor> 收集一組結果傳遞給一個結果對象的構造方法。屬性有:value,它是形式參數數組。
@Arg N/A
  • <arg>
  • <idArg>
單參數構造方法,是 ConstructorArgs 集合的一部分。屬性有:id, column, javaType, jdbcType, typeHandler, select 和 resultMap。id 屬性是布爾值,來標識用於比較的屬性,和<idArg> XML 元素類似。
@TypeDiscriminator 方法 <discriminator> 一組實例值被用來決定結果映射的表現。屬性有:column, javaType, jdbcType, typeHandler 和 cases。cases 屬性是實例數組。
@Case N/A <case> 單獨實例的值和它對應的映射。屬性有:value, type, results。results 屬性是結果數組,所以這個註解和實際的 ResultMap 很類似,由下面的 Results 註解指定。
@Results 方法 <resultMap> 結果映射的列表,包含了一個特別結果列如何被映射到屬性或字段的詳情。屬性有:value, id。value 屬性是 Result 註解的數組。這個 id 的屬性是結果映射的名稱。
@Result N/A
  • <result>
  • <id>
在列和屬性或字段之間的單獨結果映射。屬性有:id, column, javaType, jdbcType, typeHandler, one, many。id 屬性是一個布爾值,來標識應該被用於比較(和在 XML 映射中的<id>類似)的屬性。one 屬性是單獨的聯繫,和 <association> 類似,而 many 屬性是對集合而言的,和<collection>類似。它們這樣命名是爲了不名稱衝突。
@One N/A <association> 複雜類型的單獨屬性值映射。屬性有:select,已映射語句(也就是映射器方法)的全限定名,它能夠加載合適類型的實例。fetchType會覆蓋全局的配置參數 lazyLoadingEnabled。注意聯合映射在註解 API中是不支持的。這是由於 Java 註解的限制,不容許循環引用。
@Many N/A <collection> 映射到複雜類型的集合屬性。屬性有:select,已映射語句(也就是映射器方法)的全限定名,它能夠加載合適類型的實例的集合,fetchType 會覆蓋全局的配置參數 lazyLoadingEnabled。注意 聯合映射在註解 API中是不支持的。這是由於 Java 註解的限制,不容許循環引用
@MapKey 方法   這是一個用在返回值爲 Map 的方法上的註解。它可以將存放對象的 List 轉化爲 key 值爲對象的某一屬性的 Map。屬性有: value,填入的是對象的屬性名,做爲 Map 的 key 值。
@Options 方法 映射語句的屬性 這個註解提供訪問大範圍的交換和配置選項的入口,它們一般在映射語句上做爲屬性出現。Options 註解提供了通俗易懂的方式來訪問它們,而不是讓每條語句註解變複雜。屬性有:useCache=true, flushCache=FlushCachePolicy.DEFAULT, resultSetType=FORWARD_ONLY, statementType=PREPARED, fetchSize=-1, timeout=-1, useGeneratedKeys=false, keyProperty="id", keyColumn="", resultSets=""。值得一提的是, Java 註解沒法指定 null 值。所以,一旦你使用了 Options 註解,你的語句就會被上述屬性的默認值所影響。要注意避免默認值帶來的預期之外的行爲。

       注意: keyColumn 屬性只在某些數據庫中有效(如 Oracle、PostgreSQL等)。請在插入語句一節查看更多關於 keyColumn 和 keyProperty 二者的有效值詳情。
  • @Insert
  • @Update
  • @Delete
  • @Select
方法
  • <insert>
  • <update>
  • <delete>
  • <select>
這四個註解分別表明將會被執行的 SQL 語句。它們用字符串數組(或單個字符串)做爲參數。若是傳遞的是字符串數組,字符串之間先會被填充一個空格再鏈接成單個完整的字符串。這有效避免了以 Java 代碼構建 SQL 語句時的「丟失空格」的問題。然而,你也能夠提早手動鏈接好字符串。屬性有:value,填入的值是用來組成單個 SQL 語句的字符串數組。
  • @InsertProvider
  • @UpdateProvider
  • @DeleteProvider
  • @SelectProvider
方法
  • <insert>
  • <update>
  • <delete>
  • <select>
容許構建動態 SQL。這些備選的 SQL 註解容許你指定類名和返回在運行時執行的 SQL 語句的方法。(自從MyBatis 3.4.6開始,你能夠用 CharSequence 代替 String 來返回類型返回值了。)當執行映射語句的時候,MyBatis 會實例化類並執行方法,類和方法就是填入了註解的值。你能夠把已經傳遞給映射方法了的對象做爲參數,"Mapper interface type" 和 "Mapper method" 會通過 ProviderContext (僅在MyBatis 3.4.5及以上支持)做爲參數值。(MyBatis 3.4及以上的版本,支持多參數傳入)屬性有: type, method。type 屬性需填入類。method 需填入該類定義了的方法名。注意 接下來的小節將會討論類,能幫助你更輕鬆地構建動態 SQL。
@Param 參數 N/A 若是你的映射方法的形參有多個,這個註解使用在映射方法的參數上就能爲它們取自定義名字。若不給出自定義名字,多參數(不包括 RowBounds 參數)則先以 "param" 做前綴,再加上它們的參數位置做爲參數別名。例如 #{param1}, #{param2},這個是默認值。若是註解是 @Param("person"),那麼參數就會被命名爲 #{person}。
@SelectKey 方法 <selectKey> 這個註解的功能與 <selectKey> 標籤徹底一致,用在已經被 @Insert 或 @InsertProvider 或 @Update 或 @UpdateProvider 註解了的方法上。若在未被上述四個註解的方法上做 @SelectKey 註解則視爲無效。若是你指定了 @SelectKey 註解,那麼 MyBatis 就會忽略掉由 @Options 註解所設置的生成主鍵或設置(configuration)屬性。屬性有:statement 填入將會被執行的 SQL 字符串數組,keyProperty 填入將會被更新的參數對象的屬性的值,before 填入 true 或 false 以指明 SQL 語句應被在插入語句的以前仍是以後執行。resultType 填入 keyProperty 的 Java 類型和用 Statement、 PreparedStatement 和 CallableStatement 中的 STATEMENT、 PREPARED 或 CALLABLE 中任一值填入 statementType。默認值是 PREPARED。
@ResultMap 方法 N/A 這個註解給 @Select 或者 @SelectProvider 提供在 XML 映射中的 <resultMap> 的id。這使得註解的 select 能夠複用那些定義在 XML 中的 ResultMap。若是同一 select 註解中還存在 @Results 或者 @ConstructorArgs,那麼這兩個註解將被此註解覆蓋。
@ResultType 方法 N/A 此註解在使用告終果處理器的狀況下使用。在這種狀況下,返回類型爲 void,因此 Mybatis 必須有一種方式決定對象的類型,用於構造每行數據。若是有 XML 的結果映射,請使用 @ResultMap註解。若是結果類型在 XML 的 <select> 節點中指定了,就不須要其餘的註解了。其餘狀況下則使用此註解。好比,若是 @Select 註解在一個將使用結果處理器的方法上,那麼返回類型必須是 void 而且這個註解(或者@ResultMap)必選。這個註解僅在方法返回類型是 void 的狀況下生效。
@Flush 方法 N/A

注意,使用#符號和$符號的不一樣:數組

// This example creates a prepared statement, something like select * from teacher where name = ?;
@Select("Select * from teacher where name = #{name}")
Teacher selectTeachForGivenName(@Param("name") String name);

// This example creates n inlined statement, something like select * from teacher where name = 'someName';
@Select("Select * from teacher where name = '${name}'")
Teacher selectTeachForGivenName(@Param("name") String name);

四、使用

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {

	@Autowired
	private UserMapper UserMapper;

	@Test
	public void testInsert() throws Exception {
		UserMapper.insert(new UserEntity("aa", "a123456", UserSexEnum.MAN));
		UserMapper.insert(new UserEntity("bb", "b123456", UserSexEnum.WOMAN));
		UserMapper.insert(new UserEntity("cc", "b123456", UserSexEnum.WOMAN));

		Assert.assertEquals(3, UserMapper.getAll().size());
	}

	@Test
	public void testQuery() throws Exception {
		List<UserEntity> users = UserMapper.getAll();
		System.out.println(users.toString());
	}
	
	@Test
	public void testUpdate() throws Exception {
		UserEntity user = UserMapper.getOne(3l);
		System.out.println(user.toString());
		user.setNickName("neo");
		UserMapper.update(user);
		Assert.assertTrue(("neo".equals(UserMapper.getOne(3l).getNickName())));
	}
}

極簡xml版本

極簡xml版本保持映射文件的老傳統,優化主要體如今不須要實現dao的是實現層,系統會自動根據方法名在映射文件中找對應的sql.

一、配置

pom文件和上個版本同樣,只是application.properties新增如下配置

mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml

指定了mybatis基礎配置文件和實體類映射文件的地址

mybatis-config.xml 配置

<configuration>
	<typeAliases>
		<typeAlias alias="Integer" type="java.lang.Integer" />
		<typeAlias alias="Long" type="java.lang.Long" />
		<typeAlias alias="HashMap" type="java.util.HashMap" />
		<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
		<typeAlias alias="ArrayList" type="java.util.ArrayList" />
		<typeAlias alias="LinkedList" type="java.util.LinkedList" />
	</typeAliases>
</configuration>

這裏能夠添加一些mybatis基礎的配置

二、添加User的映射文件

<mapper namespace="com.neo.mapper.UserMapper" >
    <resultMap id="BaseResultMap" type="com.neo.entity.UserEntity" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="userName" property="userName" jdbcType="VARCHAR" />
        <result column="passWord" property="passWord" jdbcType="VARCHAR" />
        <result column="user_sex" property="userSex" javaType="com.neo.enums.UserSexEnum"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR" />
    </resultMap>
    
    <sql id="Base_Column_List" >
        id, userName, passWord, user_sex, nick_name
    </sql>

    <select id="getAll" resultMap="BaseResultMap"  >
       SELECT 
       <include refid="Base_Column_List" />
	   FROM users
    </select>

    <select id="getOne" parameterType="java.lang.Long" resultMap="BaseResultMap" >
        SELECT 
       <include refid="Base_Column_List" />
	   FROM users
	   WHERE id = #{id}
    </select>

    <insert id="insert" parameterType="com.neo.entity.UserEntity" >
       INSERT INTO 
       		users
       		(userName,passWord,user_sex) 
       	VALUES
       		(#{userName}, #{passWord}, #{userSex})
    </insert>
    
    <update id="update" parameterType="com.neo.entity.UserEntity" >
       UPDATE 
       		users 
       SET 
       	<if test="userName != null">userName = #{userName},</if>
       	<if test="passWord != null">passWord = #{passWord},</if>
       	nick_name = #{nickName}
       WHERE 
       		id = #{id}
    </update>
    
    <delete id="delete" parameterType="java.lang.Long" >
       DELETE FROM
       		 users 
       WHERE 
       		 id =#{id}
    </delete>
</mapper>

 

三、編寫Dao層的代碼

public interface UserMapper {
	
	List<UserEntity> getAll();
	
	UserEntity getOne(Long id);

	void insert(UserEntity user);

	void update(UserEntity user);

	void delete(Long id);

}

對比上一步這裏所有隻剩了接口方法

四、使用

使用和註解版本沒有區別。

如何選擇

兩種模式各有特色,註解版適合簡單快速的模式,相似微服務那種一個服務對應一個數據庫。

老傳統模式比適合大型項目,能夠靈活的動態生成SQL,方便修改SQL。

相關文章
相關標籤/搜索