ORM 框架的目的是简化程式设计中的资料库操作,经过这么多年的发展,基本上活到现在的就剩下两家了,一个是宣称可以不用写SQL 的Hibernate ,一个是对SQL 非常友好的Mybaties ,,两者各有特点,在企业级系统开发中可以根据需求灵活使用。发现一个有趣的现象:传统企业大都喜欢使用Hibernate ,网际网路行业通常使用Mybatis 。
Hibernate 特点就是所有的SQL 都用Java 程式码来生成,不用跳出程式去写(看) SQL ,有着程式设计的完整性,发展到最顶端就是Spring Data Jpa 这种模式了,基本上根据方法名就可以生成对应的SQL 了,有不太了解的可以看笔者的前两篇文章Spring Boot (三): ORM 框架JPA 与连线池Hikari 和Spring Boot (六): 为JPA 插上翅膀的QueryDSL。
Mybatis 初期使用比较麻烦,需要各种配置档案、实体类、Dao 层对映关联、还有一大推其它配置。当然Mybatis 也发现了这种弊端,初期开发了generator 可以根据表结果自动生产实体类、配置档案和Dao 层程式码,可以减轻一部分开发量;后期也进行了大量的优化可以使用注解了,自动管理Dao 层和配置档案等,发展到最顶端就是今天要讲的这种模式了,mybatis-spring-boot-starter 就是Spring Boot + Mybatis 可以完全注解不用配置档案,也可以简单配置轻松上手。
首先建立父工程spring-boot-mybatis
,引入全域性依赖包,如下:
程式码清单:spring-boot-mybatis/pom.xml
***
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.0
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
建立子工程 spring-boot-mybatis-xml
2.1.1 配置档案
application.yml 配置档案如下:
程式码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.yml
***
server:
port: 8080
spring:
application:
name: spring-boot-mybatis-xml
datasource:
url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
auto-commit: true
minimum-idle: 2
idle-timeout: 60000
connection-timeout: 30000
max-lifetime: 1800000
pool-name: DatebookHikariCP
maximum-pool-size: 5
mybatis:
type-aliases-package: com.springboot.springbootmybatisxml.model
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
spring.datasource.*
相关配置,资料来源会自动注入到sqlSessionFactory
中,sqlSessionFactory
会自动注入到Mapper中。mybatis-config.xml 配置档案如下:
程式码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml
***
2.1.2 Mapper 对映档案
程序码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml
***
id, nick_name, age, create_date
select uuid() as id from dual
INSERT INTO
user
(id, nick_name, age, create_date)
VALUES
(#{id}, #{nickName}, #{age}, #{createDate})
UPDATE
user
SET
nick_name = #{nickName},
age = #{age},
create_date = #{createDate}
WHERE
id = #{id}
DELETE FROM
user
WHERE
id = #{id}
标签作判断2.1.3 Mapper 层程式码
程式码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/springboot/springbootmybatisxml/mapper/UserMapper.java
***
public interface UserMapper {
List getAll();
User getUser(String id);
Long insertUser(User user);
Long updateUser(User user);
Long deleteUser(String id);
}
2.1.4 启动主类
程式码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/springboot/springbootmybatisxml/SpringBootMybatisXmlApplication.java
***
@SpringBootApplication
@MapperScan("com.springboot.springbootmybatisxml.mapper")
public class SpringBootMybatisXmlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMybatisXmlApplication.class, args);
}
}
@MapperScan
或者直接在Mapper类上增加注解@Mapper
,两种方法起到的结果是一样的。不过建议选择在启动主类上配置@MapperScan
,不然在每个Mapper类上加注解也麻烦,还容易漏加。2.2.1 配置
配置档案application.yml 如下:
程式码清单:
***
mybatis:
type-aliases-package: com.springboot.springbootmybatisannotation.model
2.2.2 Mapper 类
注解版的核心就是这个类,所有的SQL 都在这个类里面,程式码如下:
程式码清单:
***
public interface UserMapper {
@Select("select * from user")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "nickName", column = "nick_name"),
@Result(property = "age", column = "age"),
@Result(property = "createDate", column = "create_date")
})
List getAll();
@Select("SELECT * FROM user WHERE id = #{id}")
@Results({
@Result(property = "nickName", column = "nick_name")
})
User getUser(String id);
@Insert("INSERT INTO user(id, nick_name, age, create_date) VALUES(#{id}, #{nickName}, #{age}, #{createDate})")
@SelectKey(keyProperty = "id", resultType = String.class, before = true, statement = "select uuid() as id from dual")
Long insertUser(User user);
@Update("UPDATE user SET nick_name = #{nickName}, age = #{age} WHERE create_date = #{createDate}")
Long updateUser(User user);
@Delete("DELETE FROM user WHERE id = #{id}")
Long deleteUser(String id);
}
注意:使用# 符号和$ 符号是不同的
#{}
使用#{}
意味着使用的预编译的语句,即在使用jdbc时的preparedStatement , sql语句中如果存在引数则会使用?作占位符。
${}
使用${}
时的sql不会当做字串处理,是什么就是什么,如上边的语句:select * from table1 where id=${id}在呼叫这个语句时控制台列印的为:select * from table1 where id =2 ,假设传的引数值为2
从上边的介绍可以看出这两种方式的区别,最好是能用#{}
则用它,可以防止sql注入,且是预编译的,在需要原样输出时才使用${}
。