SpringBoot的便捷性就在于其xml配置文件非常少,几乎都可以用注解代替。

传统的Mybatis主要也是依赖于xml文件,那么当Mybatis遇上SpringBoot时,如何用注解取代其xml配置文件呢?

1,Mybatis的config.xml文件

mybatis_config.xml文件是Mybatis的条件配置文件,它有很多项,具体配置可参照下面代码

/p>
"http://ibatis.apache.org/dtd/ibatis-3-config.dtd">

要取代这个文件,我们可以引入MybatisAutoConfiguration配置文件

@Configuration
@MapperScan(basePackages = {"${mybatis.type-dao-package:com.biticcf.ocean.sea.domain.dao}"},
sqlSessionFactoryRef = "sqlSessionFactory")
@EnableTransactionManagement
@AutoConfigureOrder(-100)
@AutoConfigureAfter({MybatisAutoConfiguration.class})
public class DatasourceConfig {
...
}

然后即可启用MybatisProperties属性配置文件,使用yml对Mybatis属性进行配置:

这里要注意:

MybatisProperties文件里有两个配置参数项:

configLocation:这个是用来指定mybatis_config.xml文件地址;

configuration:这里是通过注解的方式自定义配置文件;

在这里如果配置了configLocation,那么configuration将不再起作用!

因此,我们为了通过配置文件来配置属性的话,configLocation一定不能配置!

接下来,我们通过yml来替换xml配置文件

mybatis:

# config-location: classpath:bean/mybatis/mybatis_config.xml
# mapper-locations: classpath:/bean/mybatis/mapping/*.xml
type-aliases-package: com.biticcf.ocean.sea.domain.dao.po
type-dao-package: com.biticcf.ocean.sea.domain.dao
executorType: REUSE
configuration:
cache-enabled: true
lazy-loading-enabled: true
aggressive-lazy-loading: false
multiple-result-sets-enabled: true
use-column-label: true
use-generated-keys: true
auto-mapping-behavior: FULL
default-executor-type: REUSE
default-statement-timeout: 180
map-underscore-to-camel-case: true
default-fetch-size: 200
local-cache-scope: SESSION
jdbc-type-for-null: OTHER
lazy-load-trigger-methods: equals,clone,hashCode,toString
log-prefix: [mybatis]
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pagehelper:
helper-dialect: mysql
offset-as-page-num: false
row-bounds-with-count: true
page-size-zero: false
reasonable: false
support-methods-arguments: false
return-page-info: none

其中,mybatis.configuration对应了xml文件中的settings配置属性,mybatis.interceptors对应了xml文件中的plugins,这部功能只需要引入分页组件即可,代码如下:

com.github.pagehelper
pagehelper-spring-boot-starter
1.2.10

这样配置完毕,mybatis_config.xml就可以完全替换了。

2,Mybatis的mapper.xml文件

Mybatis的mapper.xml文件是数据库映射文件,里面包含了数据库相关定义、缓存相关定义、数据操作sql定义等,具体代码如下:

ID,
GOODS_CODE,
GOODS_SN,
STATUS,
CREATE_TIME,
UPDATE_TIME,
VERSION
parameterType="com.beyonds.phoenix.coral.domain.dao.po.DemoPo"
useGeneratedKeys="true"
keyProperty="id">
INSERT INTO WD_DEMO_INFO
(
GOODS_CODE,
GOODS_SN,
STATUS,
CREATE_TIME,
UPDATE_TIME,
VERSION
)
VALUES
(
#{goodsCode},
#{goodsSn},
0,
now(),
now(),
0
)
parameterType="com.beyonds.phoenix.coral.domain.dao.po.DemoPo"
useGeneratedKeys="true"
keyProperty="id">
INSERT INTO WD_DEMO_INFO
(
GOODS_CODE,
GOODS_SN,
STATUS,
CREATE_TIME,
UPDATE_TIME,
VERSION
)
VALUES
(
#{item.goodsCode},
#{item.goodsSn},
0,
now(),
now(),
0
)

下面,我们来替换掉这个文件。

2.1,在配置中去掉xml路径

mybatis:

# config-location: classpath:bean/mybatis/mybatis_config.xml
# mapper-locations: classpath:/bean/mybatis/mapping/*.xml
type-aliases-package: com.biticcf.ocean.sea.domain.dao.po
type-dao-package: com.biticcf.ocean.sea.domain.dao

2.2,在DAO接口中实现二级缓存

@CacheNamespace(eviction = LruCache.class, flushInterval = 60000L, size = 1024, readWrite = true)
@Mapper
public interface DemoDAO {
...
}

注意,此时的DAO接口一定要加上@Mapper注解。

2.3,在DAO接口中实现字段映射

/**
* 根据id查询
* @param id ID值
* @return 查询结果
*/
@Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
@Results(id = "demoMap", value = {
@Result(property = "id", column = "id", id = true, javaType = Long.class, jdbcType = JdbcType.BIGINT),
@Result(property = "goodsCode", column = "GOODS_CODE", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "goodsSn", column = "GOODS_SN", javaType = String.class, jdbcType = JdbcType.VARCHAR),
@Result(property = "status", column = "STATUS", javaType = Byte.class, jdbcType = JdbcType.TINYINT),
@Result(property = "createTime", column = "CREATE_TIME", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP),
@Result(property = "updateTime", column = "UPDATE_TIME", javaType = Date.class, jdbcType = JdbcType.TIMESTAMP),
@Result(property = "version", column = "VERSION", javaType = Integer.class, jdbcType = JdbcType.INTEGER)
})
@Select("SELECT * FROM WD_DEMO_INFO WHERE ID = #{id}")
DemoPo queryById(@Param("id") long id);

这里,@Results(id = "demoMap")定义了一个名称是demoMap映射Map,在当前DAO文件(Namespace)中的其他sql下可以使用;

@Options是用来定义如何使用缓存的。

2.4,在DAO接口中使用Map映射

/**
* +查询列表
* @return 查询结果
*/
@Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
@Select("SELECT * FROM WD_DEMO_INFO ORDER BY ID DESC")
@ResultMap(value = {"demoMap"})
List queryList();

2.5,在DAO接口中使用SqlProvider

SqlProvider是用来实现复杂sql语句和动态sql语句的。

/**
* +保存一条记录
* @param demoPo 数据记录
* @return 保存成功条数
*/
@Options(useCache = true, flushCache = Options.FlushCachePolicy.TRUE, useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@InsertProvider(type = DemoSqlProvider.class, method = "insert")
int insert(DemoPo demoPo);

其中,DemoSqlProvider实现如下:

public class DemoSqlProvider {
/**
* +添加数据sql
* @param demoPo 传入对象值
* @return 拼成的sql
*/
public String insert(DemoPo demoPo) {
return new SQL() {
{
INSERT_INTO("`WD_DEMO_INFO`");
INTO_COLUMNS("`GOODS_CODE`", "`GOODS_SN`", "`STATUS`", "`CREATE_TIME`", "`UPDATE_TIME`", "`VERSION`");
INTO_VALUES("#{goodsCode}", "#{goodsSn}", "0", "now()", "now()", "0");
}
}.toString();
}
/**
* +批量添加数据sql
* @param map 批量数据
* @return 拼成的sql
*/
public String inserts(Map> map) {
List demoList = map.get("list");
if (demoList == null || demoList.isEmpty()) {
return null;
}
StringBuilder sql = new StringBuilder("");
sql.append("INSERT INTO `WD_DEMO_INFO`");
sql.append("(`GOODS_CODE`, `GOODS_SN`, `STATUS`, `CREATE_TIME`, `UPDATE_TIME`, `VERSION`)");
sql.append("VALUES");
for (int i = 0; i < demoList.size(); i++) {
sql.append("(#{list[" + i + "].goodsCode}, #{list[" + i + "].goodsSn}, 0, now(), now(), 0),");
}
sql.deleteCharAt(sql.length() - 1);
sql.append(";");
return sql.toString();
}
}

在这里需要注意的是,SqlProvider的方法中,只能有一个参数,可以是Map(或者Map等价的普通bean)。Mybatis会自动把多个参数包装成Map,用@Param("id")的value作为键值。

另外,目前Mybatis提供的内建SQL()方法,还没提供批量添加的功能,需要手动拼装,如上面的inserts方法。

完整代码请参照https://github.com/biticcf/ocean-sea-platform.git

-End-