SpringBoot整合Mybatis之入门篇
使用springboot整合mybatis使用
1、入门案例
在idea中创建springboot项目,勾选mybatis和jdbc
首先看下pom.xml依赖:
# 应用名称
spring.application.name=springboot-mybatis-test-one
#下面这些内容是为了让MyBatis映射
#指定Mybatis的Mapper文件。从这里可以看到以后的mappers文件都需要写在类路径下的mappers文件夹下
mybatis.mapper-locations=classpath:mappers/*xml
#指定Mybatis的实体目录
mybatis.type-aliases-package=com.guang.springbootmybatistestone.mybatis.entity
# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址。默认的地址和数据库表名
spring.datasource.url=jdbc:mysql://localhost:3306/blue?serverTimezone=UTC
# 数据库用户名&密码:
spring.datasource.username=***
spring.datasource.password=***
# 需要查看打印出来的sql语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
在上面填写自己的数据库IP地址和对应的表名以及账号密码即可。
编写对应的实体类:
@Data
public class Account {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
编写对应的接口:
public interface AccountDao {
/**
* 查询所有的账号
* @return
*/
List findAllAccount();
}
这里需要注意的是因为没有在接口上添加注解,该接口将会根据动态代码来生成对应的代理类,也需要注册到容器中来。
所以需要在接口上添加注解,但是因为接口在后续中需要不断的来进行添加,所以直接来启动类上加上注解来扫描制定路径下的包即可
@SpringBootApplication
@MapperScan("com.guang.springbootmybatistestone.mybatis.dao")
public class SpringbootMybatisTestOneApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootMybatisTestOneApplication.class, args);
}
}
编写接口对应的xml文件:
<?xml version="1.0" encoding="utf-8"?>
那么来进行测试:
@Autowired
private AccountDao accountDao;
@Test
public void testfindAllAccount(){
List allAccount = accountDao.findAllAccount();
allAccount.forEach(System.out::println);
}
因为在上面添加了打印日志,所以直接在控制台上来进行查看:
==> Preparing: select * from user
==> Parameters:
<== Columns: id, username, birthday, sex, address
可以看到打印出来的SQL语句。
2、条件查询
2.1、方法参数
2.1.2、方法参数只有一个
有以下几种类型。
基本类型、pojo类、map、list
其实如果只有一个的话,推荐使用@Param注解在接口方法中直接指定在ongl表达式中的填写的内容。
基本类型
看接口:
/**
* 根据用户Id来进行查询
* @param userId
* @return
*/
User findUserById(@Param("id") Integer userId);
对应的xml文件:
测试一下:
@Test
public void testfindUserById(){
User user = accountDao.findUserById(42);
log.info("对应的user对应的数据是-------->>>>>>>{}",user);
}
查看控制台打印即可。
这里想说的是@Param("id")中注解的value值就是我们在xml文件中,#{}中所写的内容。至于这里是为什么,那么之后也可以来进行补充说明。但是推荐的是使用的时候都给加上。
pojo类型
接口:
/**
* 根据用户来进行条件查询
* @param user
* @return
*/
List findAllAccountByName(@Param("user") User user);
对应的xml
这里就不在来写测试类了,本地测试通过了,就不在上来进行粘贴了。
map类型
接口:
/**
* 通过map来进行查询用户
* @param map
* @return
*/
User findUserByMap(@Param("hellomap") Map map);
对应的xml文件
在测试的时候,需要注意的事情是,map中的key要和xml文件中#{}中填充的保持一致,因为我在接口中对map进行了重新定义,所以也需要来补充上。
@Test
public void testfindUserByMap(){
Map map = new HashMap<>();
map.put("name","tony");
map.put("add","北京");
User user = accountDao.findUserByMap(map);
log.info("user对应的数据是:-------->>>>> {}",user);
}
list类型
/**
* 通过ID集合来查询满足条件的用户
* @param idList
* @return
*/
List findUserByIdList(@Param("ids") List idList);
在这里需要使用到mybatis中的标签来进行使用。
对应的xml文件
其中,需要说明的是,index指的是下标,而不是里面的元素的值。item是每个下标的值
2.1.3、方法参数多个
将方法参数中只有一个的类型中的类型进行组装即可。
其他的方法和方法参数是一个的差不了多少。
2.2、方法返回值
从上面的测试中可以看到,无论返回是一个pojo还是一个list,返回值填写的都是一个pojo类型的。
原因是因为不管是list还是其他的类型,返回的时候都会是一个类型。只不过mybatis底层来进行判断了而已。如果只是一个,那么就取出来一个;如果是多个,那么才会取出来多个。
在以前的jdbc操作中,从数据库查询出来的是一行一行的记录。但是现在在mybatis中可以自动将查询出来的数据给封装到对象中来。
这一步mybatis来给实现好了。所以这里很有必要了解一下。在mybatis中,需要将查询出来的字段和pojo类中的属性名称保持一致。
在之前的学习中,我们有一种方式来解决这个问题。那就是通过给查询出来的字段起别名。
还有一种可能也会用到的操作,那么就是开启驼峰命名操作。但是这种操作是受限的。因为如果是数据库中的表中字段就只是这种方式,那么开启这种方式就可以了。
但是mybatis中提供了一种简便的方法来进行操作。就是resultmap,强大的映射操作。尽管数据库中的字段和pojo类中的属性名称不同,通过映射也是可以将其封装好的。
在
3、关联查询
表跟表之间的关联关联通常来说分为:一对一、一对多、多对多
现在主流的两种方式,一种是类引用方式,还有另外一种是嵌套查询。个人倾向于嵌套查询,因为这样子这样子写起来很舒服。
那么分别来测试一下这两种方式,然后结合着resultMap来使用一下。
最佳操作:在进行操作之前,首先判断是一对一、一对多、多对多中的哪种关系。
然后需要自己手写出来对应的sql语句出来。
需求一:查询所有帐户表信息,及其关联的用户信息
一个账号对应着的是一个用户。一对一关系,那么应该在account类添加一个字段user类型的
下面我用嵌套查询来写了。
对应如下:
@Data
public class Account {
private Integer id;
private Integer uid;
private Double money;
private User user;
}
对应的接口:
public interface AccountDao {
/**
* 查询账号关联的用户数据
* @return
*/
List findAllAccountAndUser();
}
User类:
@Data
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
对应的接口方法:
/**
* 根据用户Id来进行查询
* @param userId
* @return
*/
User findUserById(@Param("id") Integer userId);
在AccountDao.xml配置的有:
从上面可以看到,因为是类引用方式,而且前面不是List类型,而是简单的关联查询而已。所以使用的是association,javaType。
通过select来选择使用哪个dao中的哪个方法,需要传递的参数是什么,通过column来进行传递。
需求二:查询所有用户(user)信息,以及每个用户拥有的所有帐号(account)信息
那么先分析出来是一对多的关系,那么说明需要在User表中建立list类型的属性。
@Data
public class Account {
private Integer id;
private Integer uid;
private Double money;
}
@Data
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List accountList;
}
写出来对应的接口:
public interface UserDao {
List findAllUser();
}
对应的xml文件:
AccountDao接口:
public interface AccountDao {
/**
* 通过ID来进行查询对应的account
* @param id
* @return
*/
Account findAccountById(@Param("id") Integer id);
}
对应的xml文件:
然后将对应的记录查询出来即可。
从这里可以看到如果类中的属性是集合数据类型,那么使用的是collection,对应的数据类型是ofType
需求三:现有用户表(user)和角色表(role),是多对多关系。有中间关系表user_role
那么这个就是用来练手的。
一个用户有多个角色,一个角色对应着多个用户。多对多的关系。
这种表应该先从中间表来进行查询
# 第一步:查询中间表
select * from user_role where uid = 41;
# 第二步:指定一个具体的ID
select rid from user_role where uid = 41;
# 第三步:从要查询的表中来进行查询
select * from role;
select * from role where id in (select rid from user_role where uid = 41);
# 第四步
select u.*,r.id rid,r.ROLE_NAME rolename,r.ROLE_DESC description from user u left join user_role ur on u.id = ur.UID left join role r on ur.rid = r.ID;
这就是查询出来的数据
那么开始建立起来对应的类:
@Data
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List roleList;
}
@Data
public class Role {
private Integer id;
private String roleName;
private String roleDesc;
private List users;
}
写出来对应的接口即可:
public interface UserDao {
List findAllUser();
}
对应的xml文件是:
写一个测试类直接来进行测试即可。