springboot之mybatis基础
简介
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
Mybatis与Hibernate区别
两个都是持久层框架,操作数据库,但是两者还是有区别的
hibernate:它是一个标准的orm框架,比较重量级,学习成本高.
优点:高度封装,使用起来不用写sql,开发的时候,会减低开发周期.
缺点:sql语句无法优化
应用场景:oa(办公自动化系统), erp(企业的流程系统)等,还有一些政府项目,
总的来说,在用于量不大,并发量小的时候使用.
mybatis:它不是一个orm框架, 它是对jdbc的轻量级封装, 学习成本低,比较简单
优点:学习成本低, sql语句可以优化, 执行效率高,速度快
缺点:编码量较大,会拖慢开发周期
应用场景: 互联网项目,比如电商,P2p等
总的来说是用户量较大,并发高的项目。
基础jdbc
Mybaits工作原理
工作原理解析
mybatis应用程序通过SqlSessionFactoryBuilder从mybatis-config.xml配置文件(也可以用Java文件配置的方式,需要添加@Configuration)中构建出SqlSessionFactory(SqlSessionFactory是线程安全的);
然后,SqlSessionFactory的实例直接开启一个SqlSession,再通过SqlSession实例获得Mapper对象并运行Mapper映射的SQL语句,完成对数据库的CRUD和事务提交,之后关闭SqlSession。
说明:SqlSession是单线程对象,因为它是非线程安全的,是持久化操作的独享对象,类似jdbc中的Connection,底层就封装了jdbc连接。
详细流程如下:
1、加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着<select | update | delete | insert>标签项。
2、SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。
3、SqlSession对象完成和数据库的交互:
a、用户程序调用mybatis接口层api(即Mapper接口中的方法)
b、SqlSession通过调用api的Statement ID找到对应的MappedStatement对象
c、通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象
d、JDBC执行sql。
e、借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。
首先弄懂的问题:mybatis #{}和${}的区别
他们之间的区别用最直接的话来说就是:#相当于对数据 加上 双引号,$相当于直接显示数据。
1、#对传入的参数视为字符串,也就是它会预编译,select * from user where name = #{name},比如我传一个csdn,那么传过来就是 select * from user where name = 'csdn';
2、$将不会将传入的值进行预编译,select * from user where name=${name},比如我穿一个csdn,那么传过来就是 select * from user where name=csdn;
3、#的优势就在于它能很大程度的防止sql注入,而$则不行。比如:用户进行一个登录操作,后台sql验证式样的:select * from user where username=#{name} and password = #{pwd},如果前台传来的用户名是“wang”,密码是 “1 or 1=1”,用#的方式就不会出现sql注入,而如果换成$方式,sql语句就变成了 select * from user where username=wang and password = 1 or 1=1。这样的话就形成了sql注入。
4、MyBatis排序时使用order by 动态参数时需要注意,用$而不是#
开始运用
添加依赖
<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>
</dependency>
<!-- mybatis分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-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>
注解方式
配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
username: root
password: root
#mybatis,批量定义别名
mybatis:
type-aliases-package: com.yimingkeji.mybatis.entity
mapper接口
public interface UserMapper {
@Select("select * from user")
@Results({
@Result(property = "phoneNumber", column = "phone_number"),
@Result(property = "createTime", column = "create_time", javaType = Date.class)
})
List<User> findAll();
@Select("select * from user where id = #{id}")
User findOne(int id);
@Insert("insert into user(name, age, phone_number, available, create_time) values (#{name}, #{age}, #{phoneNumber}, #{available}, #{createTime})")
int add(User user);
@Update("update user set name=#{name} where id = #{id}")
int update(User user);
@Delete("delete from user where id = #{id}")
int delete(int id);
}
mapper扫描配置
在启动类中添加@MapperScan注解
@SpringBootApplication
@MapperScan(basePackages = {"com.yimingkeji.mybatis.mapper"})//或者每个mapper接口上加 @Mapper 注解
public class MybatisApp {
public static void main(String[] args) {
SpringApplication.run(MybatisApp.class, args);
}
}
测试接口
@RestController
public class UserController1 {
@Autowired private UserMapper userMapper;
@GetMapping("user")
public List<User> list(){
return userMapper.findAll();
}
@GetMapping("user/{id}")
public User one(@PathVariable int id){
return userMapper.findOne(id);
}
@PostMapping("user")
public int add(@RequestBody User user){
return userMapper.add(user);
}
@PutMapping("user")
public int update(@RequestBody User user){
return userMapper.update(user);
}
@DeleteMapping("user/{id}")
public int del(@PathVariable int id){
return userMapper.delete(id);
}
}
xml配置方式
配置文件
#加载Mybatis配置文件
mybatis.mapper-locations = classpath:mapper/*Mapper.xml
mybatis.config-location = classpath:config/sqlMapConfig.xml
#数据源必填项
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = 123456
注:通常,若mybatis配置信息较少,只是针对基本配置无需复杂配置,则只需在application.yml文件中配置即可,否则最好配置在 mybatis-config.xml中。
编写Mapper.Xml和sqlMapConfig.xml
userMapper.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="com.liujia.springdemo.mapper.UserMapper" >
<select id="getAll" resultType="com.liujia.springdemo.entity.User" >
SELECT *
FROM user
</select>
</mapper>
sqlMapConfig.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>
<typeAliases>
</typeAliases>
</configuration>
编写mapper
public interface UserMapper {
/**
* 获取所有的user对象
*
* @return
*/
List<User> getAll();
}
编写service
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> getAll() {
return userMapper.getAll();
};
}
主运行类
@SpringBootApplication
@MapperScan(basePackages = {"com.liujia.springdemo.mapper"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
总结:
两种方式的区别
1:是否需要在application.properties中配置mapper.xml和sqlMapperConfig.xml
2:将SQL语句写在了XML中
由于第二种方式将比较繁琐的SQL语句写在了配置文件中,整个代码结构更加清晰,本人更加喜欢此种配置方式。