SpringBoot整合MyBatis框架 我们很多应用,访问数据库的方式都是JDBC等等,这些非常麻烦而又繁琐的操作,为了使得这个方式得到更好的优化,人们便开始对上帝有所诉求,上帝感到了程序猿的不幸,为了平衡各个物种的差别,同时也得给达尔文一个面子,于是诞生了MyBatis(瞎说)。
MyBatis 讲到MyBatis,就先讲明这是什么吧。它是一个主流的ORM框架。那ORM又是什么呢?
对象-关系映射(Object-Relational Mapping,简称ORM),面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。
简而言之,可以通过ORM框架去更方便的操控数据库。
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
Hibernate是全自动ORM框架,而Mybatis是半自动的。 hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。 而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理。
无论是Mybatis、Hibernate都是ORM的一种实现框架,都是对JDBC的一种封装。
最原始的MyBatis 先加入pom依赖 1 2 3 4 5 <dependency > <groupId > org.mybatis.spring.boot</groupId > <artifactId > mybatis-spring-boot-starter</artifactId > <version > 2.1.0</version > </dependency >
配置文件 1 2 3 4 5 6 7 8 spring.datasource.url =jdbc:mysql://localhost:3306/springdatajpa?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8 spring.datasource.username =root spring.datasource.password =qwe123456 spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
定义好要连接的数据库属性,这里涉及到Spring的AOP,这些都是基础配置了。
实体类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class User implements Serializable { private static final long serialVersionUID = 1L ; private int id ; private String loginName ; private String username ; private String password; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getLoginName () { return loginName; } public void setLoginName (String loginName) { this .loginName = loginName; } public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } }
也可以用插件,省略掉写这些get和set哦,后面会讲。
SQL的实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 public interface UserRepository { @Insert ("insert into tb_user(login_name ,username ,password) " + "values (#{loginName},#{username},#{password})" ) public int insertUser (User user) ; @Insert ("insert into tb_user(login_name ,username ,password) " + "values (#{loginName},#{username},#{password})" ) @Options (useGeneratedKeys=true ,keyProperty="id" ,keyColumn="id" ) public void insertGetKey (User user) ; @Select ("select * from tb_user where username = #{username}" ) @ResultMap ("userResult" ) public User selectByUsername (@Param("username" ) String username) ; @Select ("select * from tb_user" ) @Results (id="userResult" ,value={ @Result (id=true ,column="id" ,property="id" ), @Result (column="login_name" ,property="loginName" ), @Result (column="password" ,property="password" ), @Result (column="username" ,property="username" ) }) public List<User> findAll () ; @Delete ("delete from tb_user where id=#{id}" ) public void delete (final Integer id) ; @Select ("select * from tb_user where id=#{id}" ) @ResultMap ("userResult" ) public User findUserById (int id) ; @Update ("update tb_user set username=#{username}, login_name=#{loginName} where id=#{id}" ) public void update (final User user) ; }
这里是一个接口,所有的SQL实现通过注解写在函数前面,就拥有了这些功能。
服务层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Service public class UserService { @Resource private UserRepository userRepository; public int insertUser (User user) { return userRepository.insertUser(user); } public User selectByUsername (String username) { return userRepository.selectByUsername(username); } public List<User> findAll () { return userRepository.findAll(); } public void insertGetKey (User user) { userRepository.insertGetKey(user); } public void update (User user) { userRepository.update(user); } public void delete (Integer id) { userRepository.delete(id); } }
服务层并不需要做些什么,仅仅是注入持久层便可。持久层会使用它的方法,再结合注解去完成查找或查询操作。
控制层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @RestController @RequestMapping ("/user" )public class UserController { @Resource private UserService userService; @RequestMapping ("/insertUser" ) public String insertUser (User user) { return "插入数据[" +userService.insertUser(user)+"]条" ; } @RequestMapping ("/insertGetKey" ) public User insertGetKey (User user) { userService.insertGetKey(user); return user ; } @RequestMapping ("/selectByUsername" ) public User selectByUsername (String username) { return userService.selectByUsername(username); } @RequestMapping ("/findAll" ) public List<User> findAll () { return userService.findAll(); } @RequestMapping ("/update" ) public void update (User user) { userService.update(user); } @RequestMapping ("/delete" ) public void delete (Integer id) { userService.delete(id); } }
我们使用的@Resource可以寻找服务层的类去注入,从结构来看,一般都是从控制层往下直到持久层。
启动器 1 2 3 4 5 6 7 8 9 @MapperScan ("com.my.data07mybatis.repository" )@SpringBootApplication public class Data07mybatisApplication { public static void main (String[] args) { SpringApplication.run(Data07mybatisApplication.class , args ) ; } }
最后别忘了在启动器前面加入@MapperScan,它会扫描在这个包下的所有类,并将其识别为MyBatis的Mapper类,这也是MyBatis独有的注解。
XML型MyBatis 使用xml文件去完成mybatis的各种SQL,有利于集中的SQL编写和控制,使我们能够更好的完成业务,大部分公司都在用这个写法。
实体类 1 2 3 4 5 6 7 8 @Data @Alias ("user" )public class User { int id; String user_name; int sex; String note; }
在引入了Lombok之后,写一个类只需要在上面加一个@Data注解便可以了,会自动生成get和set方法。
mapper类 1 2 3 4 public interface userMapper { User find (int id ) ; }
只需要做个接口就可以了,写好要做的事件的函数头便可,其他都不用。
不过同样的,也需要在启动器中加入
1 @MapperScan ("com.example.mybatis2.mapper" )
和之前的比起来,少了个SQL语句的编写,那么SQL不用写怎么知道要干什么呢?当然不是不用,而是使用XML文件去代替:
1 2 3 4 <mapper namespace ="com.example.mybatis2.mapper.userMapper" > <select id ="find" resultType ="user" parameterType ="int" > select * from t_user where id=#{id}</select > </mapper >
这便是一个SQL语句,由namespace定位mapper类,由id确定方法头,由parametertype确定传入参数类型,而resulttype则是返回值类型啦。
记得要放在resource文件的mapper文件下哦,不然扫描不到的,具体可以根据自己的需求,在application.yml里面改。
业务层和控制层 1 2 3 4 5 6 7 8 9 10 @Service public class userService { @Autowired private userMapper user; public User find (int id) { return user.find(id); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 @RestController @RequestMapping ("/user" )public class userController { @Autowired private userService user; @RequestMapping ("/find" ) public User find (int id ) { return user.find(id); } }
和上面差不多,这里省略了其他方法。
同样的,也需要在启动器中加入MapperScan(),去扫描dao层(持久层)的数据哦。
测试 在浏览器输入:
1 http://localhost:8888/user/find?id=1
便看到结果了:
。
。
。
。
。
。
但,这样还是太麻烦了,咱们还是用更偷懒的办法吧。
高级偷懒法:MyBatis-Puls MyBatis-Puls,可以让你不写SQL哦。。。
请看:
在pom文件中加入MyBatis-Puls依赖:: 1 2 3 4 5 <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.0.6</version > </dependency >
MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
建议在编程的时候有个好习惯,多加点插件。
1 2 3 4 5 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <optional > true</optional > </dependency >
lombok是个好东西,谁用谁知道。
application.yml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 mybatis-plus: mapper-locations: classpath:/mapper/*Mapper.xml spring: datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/springtest?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8 driver-class-name: com.mysql.cj.jdbc.Driver tomcat: max-idle: 10 max-wait: 10000 max-active: 50 initial-size: 5 server: port: 8888
config的配置: 1 2 3 @Configuration @MapperScan ("com.example.mybatis.mapper" )public class MyBatisConfig {}
UserMapper 1 2 3 4 <?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.example.mybatis.mapper.UserMapper" > </mapper >
其实不加入这个也可以,没有影响。
建立数据库 1 2 3 4 5 6 7 CREATE TABLE tbl_user` ( user_id BIGINT(20) NOT NULL COMMENT '主键ID',` user_name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',` user_age INT(11) NULL DEFAULT NULL COMMENT '年龄',` PRIMARY KEY (user_id)` ) charset = utf8;`
业务编写 实体类 1 2 3 4 5 6 7 8 9 @Data @TableName ("tbl_user" )public class User { @TableId (value = "user_id" ) private Long userId; private String userName; private Integer userAge; }
@Data能够自动构造get和set方法。
@TableName进行绑定操作
同时也可以使用@Alias去指定别名
Mapper类 1 public interface UserMapper extends BaseMapper <User > {}
接口什么都不需要不用写。
Service接口 1 2 3 4 5 6 7 public interface UserService extends IService <User > { int insertUser ( User user ) ; int updateUser ( User user ) ; int deleteUser ( User user ) ; User findUserByName ( String userName ) ; IPage getUserPage (Page page, User user ) ; }
在服务层接口定义好要进行的操作。
实现Service层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Service @AllArgsConstructor public class UserServiceImpl extends ServiceImpl <UserMapper , User > implements UserService { @Override public int insertUser (User user) { return baseMapper.insert( user ); } @Override public int updateUser (User user) { return baseMapper.updateById( user ); } @Override public int deleteUser (User user) { return baseMapper.deleteById( user.getUserId() ); } @Override public User findUserByName ( String userName ) { return null ; } @Override public IPage getUserPage (Page page, User user) { return null ; } }
可以发现,这里的增删改查,通通都不用写SQL,简直人类福音啊。因为大部分繁琐的SQL语句,都被封装在baseMapper里面了。
Controller层 最后的就是控制层了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @RestController @RequestMapping ("/user" )public class UserContorller { @Autowired private UserService userService; @PostMapping ( value = "/insert" ) public Object insert ( @RequestBody User user ) { return userService.insertUser( user ); } @PostMapping ( value = "/update" ) public Object update ( @RequestBody User user ) { return userService.updateUser( user ); } @PostMapping ( value = "/delete" ) public Object delete ( @RequestBody User user ) { return userService.deleteUser( user ); } @GetMapping ( value = "/getUserByName" ) public Object getUserByName ( @RequestParam String userName ) { return userService.findUserByName( userName ); } }
这样就好了,开始尝试一下把。
先打开postman,在输入:
多输入几条,最后再去数据库查看一下。
果然都输入进去了,那么再试试更改:
看看数据库:
发现也成功了,删除就不演示了。这样的方式,省略了大量的SQL语句,同样将数据传入了数据库。
是不是一点SQL都不用写,只用写实体类,再调用方法就行了。很棒吧。
。
。
。
。
。
还是太麻烦了,我懒,我实体类都不想写,我想让实体类都自己生成。
。
。
行吧,我告诉你一个更好的办法,自动生成代码!
究极偷懒法:Mybatis-Generator 这个能够让你自动生成代码,连实体类都不用写哦。
方法如下:
引入依赖 1 2 3 4 5 6 <dependency > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-core</artifactId > <version > 1.3.7</version > <scope > provided</scope > </dependency >
插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <plugin > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-maven-plugin</artifactId > <version > 1.3.7</version > <configuration > <configurationFile > src/main/resources/mybatis-generator.xml</configurationFile > <overwrite > true</overwrite > </configuration > <dependencies > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.11</version > </dependency > </dependencies > </plugin >
配置 MyBatis Generator 也需要一个 xml格式的配置文件,该文件的位置配在了上文 引入 MyBatis Generator Maven 插件的 xml配置里,即 src/main/resources/mybatis-generator.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration > <context id ="MySql" defaultModelType ="flat" > <plugin type ="org.mybatis.generator.plugins.SerializablePlugin" /> <jdbcConnection driverClass ="com.mysql.jdbc.Driver" connectionURL ="jdbc:mysql://localhost:3306/springtest?serverTimezone=UTC" userId ="root" password ="123456" /> <javaModelGenerator targetPackage ="com.example.mybatis4.entity" targetProject ="src/main/java" > </javaModelGenerator > <sqlMapGenerator targetPackage ="mapper" targetProject ="src/main/resources" > </sqlMapGenerator > <javaClientGenerator targetPackage ="com.example.mybatis4.mapper" targetProject ="src/main/java" type ="XMLMAPPER" > </javaClientGenerator > <table tableName ="tbl_user" > <property name ="modelOnly" value ="false" /> </table > </context > </generatorConfiguration >
上面 xml中几个关键的配置简介如下:
jdbcConnection:数据库连接配置
javaModelGenerator:指定自动生成的 POJO置于哪个包下
sqlMapGenerator:指定自动生成的 mapper.xml置于哪个包下
javaClientGenerator:指定自动生成的 DAO接口置于哪个包下
table tableName:指定数据表名,可以使用_和%通配符
记得一定要配置好,具体可以对照着配置。
运行 双击右边的MyBatis Generator:
看看效果吧:
这样,就连实体类都自动生成了。
。
。
。
。
。
。
我还想。。。让数据库自己跑到后端,自己动,可以吗?
。
。
项目地址:
https://github.com/Antarctica000/SpringBoot/tree/master/mybatis
https://github.com/Antarctica000/SpringBoot/tree/master/mybatis2
https://github.com/Antarctica000/SpringBoot/tree/master/mybatis3
https://github.com/Antarctica000/SpringBoot/tree/master/mybatis4