🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 添加依赖 mybatis依赖和msyql连接驱动 ~~~ <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <!-- <version>5.1.48</version>--> <version>8.0.18</version> </dependency> <!-- mybatis分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> </dependency> ~~~ # 配置文件 ~~~ # DB配置 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/app?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=root ~~~ ~~~ #在执行查询后,可以将数据库的NN\_NN格式字段,在java结果集对象中自动转换成驼峰命名参数 mybatis.configuration.mapUnderscoreToCamelCase=true ~~~ ~~~ # 打印SQL日志到控制台 logging.level.你的包名.mybatis接口包=debug ~~~ ~~~ mybatis.type-aliases-package=com.jdxia.model ~~~ # pojo层 ~~~ @Data public class User { private Long id; private String username; } ~~~ # mapper层 ~~~ @Repository @Mapper public interface UserMapper { @Select("select * from user where id = #{id}") public User findById(Long id); } ~~~ `@Mapper`:声明一个mybatis的dao接口,会被spring boot扫描到 `@Select`:声明一个查询方法,相应的增删改使用`@Insert @Delete @Update` `List`:返回集合。如果只返回一个结果,返回值是User。如果是增删改方法返回值是int `User param`:传参,`#{id}`就是param对象的id值 ## 传参方式 ### 直接使用 在 SQL 中使⽤ `#{id}` 来接收同名参数 ~~~ @Delete("DELETE FROM users WHERE id =#{id}") void delete(Long id); ~~~ ### 使用@Param 如果你的映射⽅法的形参有多个,这个注解使⽤在映射⽅法的参数上就能为它们取⾃定义名字。 若不给出⾃定义名字,多参数则先以 "param" 作前缀,再加上它们的参数位置作为参数别名。例如,`#{param1}`、`# {param2}`,这个是默认值。如果注解是 `@Param("person")`,那么参数就会被命名为 `#{person}`。 ~~~ @Select("SELECT * FROM users WHERE user_sex = #{user_sex}") List<User> getListByUserSex(@Param("user_sex") String userSex); ~~~ ### 使用map 需要传送多个参数时,可以考虑使⽤ Map ~~~ @Select("SELECT * FROM users WHERE username=#{username} AND user_sex = #{user_sex}") List<User> getListByNameAndSex(Map<String, Object> map); ~~~ 使⽤时将参数依次加⼊到 Map 中即可 ~~~ Map param= new HashMap(); param.put("username","aa"); param.put("user_sex","MAN"); List<User> users = userMapper.getListByNameAndSex(param); ~~~ ## 使用对象 在执⾏时,系统会⾃动读取对象的属性并值赋值到同名的 `#{xxx}` 中 ~~~ @Insert("INSERT INTO users(userName,passWord,user_sex) VALUES(#{userName}, #{passW ord}, #{userSex})") void insert(User user); ~~~ # 启动处 ~~~ @SpringBootApplication @MapperScan("com.jdxia.mapper") //一定要加这个,这个是mapper(dao)所对应的包路径 public class BootDemoApplication { public static void main(String[] args) { SpringApplication.run(BootDemoApplication.class, args); } } ~~~ # 控制器层 ~~~ @RestController public class IndexController { @Autowired private UserMapper userMapper; //报红线不用管,你也可以在他那加个@Repository @GetMapping("/queryUser") @ResponseBody public User queryUser() { User users = userMapper.findById(1L); return users; } } ~~~ # 结果映射 ## 字段映射 `@Results` 如果结果集不是JAVA对象而是Map,map中的列名会和数据库中的NN\_NN一样,是不会自动驼峰转换的。可以使用@Result来指明结果映射,同样也适用JAVA对象 ~~~ @Results({ @Result(property="nnNn",column="NN_NN") }) @Select("select * from user") public List<Map> findAll(); ~~~ 使用`List<Map>`不用去维护pojo,适于用数据库字段不确定或经常变化的场景。但是程序的可读性、可维护性不如`List<User>` --- `user_sex`、`nick_name` 两个属性加了下划线和实体类属性名不⼀致,另外 `user_sex` 使⽤了枚举,使⽤ @Results 和 @Result 即可解决这样的问题 ~~~ @Select("SELECT * FROM users") @Results({ @Result(property = "userSex", column = "user_sex", javaType = UserSexEnum.class), @Result(property = "nickName", column = "nick_name") }) List<UserEntity> getAll(); ~~~ ## 可复用的`@Results` 声明时给id赋值为user ~~~ @Results(id="user", value={ @Result(property="nnNn",column="NN_NN") }) ~~~ 在其他 方法中,重复使用id为user的结果映射 `@ResultMap("user")` # 分页 要在pom.xml中引入分页插件,分页逻辑写在service层 ~~~ @Service @Transactional public class HelloServiceImpl { @Autowired MybatisDao mybatisDao; public void find(){ //分页插件: 查询第1页,每页10行 Page<User> page =PageHelper.startPage(1, 10); mybatisDao.findAll(); //数据表的总行数 page.getTotal(); //分页查询结果的总行数 page.size(); //第一个User对象,参考list,序号0是第一个元素,依此类推 page.get(0); } ~~~ 执行原理:PageHelper.startPage会拦截下一个sql,也就是mybatisDao.findAll()的SQL。并且根据当前数据库的语法,把这个SQL改造成一个高性能的分页SQL,同时还会查询该表的总行数,具体可以看SQL日志。 `PageHelper.startPage`和`mybatisDao.findAll()`最好紧跟在一起,中间不要有别的逻辑,否则可能出BUG。 `Page<User> page`:相当于一个list集合,findAll()方法查询完成后,会给page对象的相关参数赋值 # 回传ID 假设数据库表的ID主键是自动增长的,现在添加一条数据,想要得到这条数据自动增长的ID,方法如下 dao层 `useGeneratedKeys=true`:获取数据库生成的主键 `keyProperty="id"`:把主键值存入User param对象的id属性 ~~~ @Insert("insert into user(name) values(#{name})") @Options(useGeneratedKeys=true,keyProperty="id") public int add(User param); ~~~ service层 ~~~ User user = new User(); user.setName("tom"); mybatisDao.add(user); System.out.println("回传ID值:"+user.getId()); ~~~ # 存储过程 这是一个mysql存储过程,传入一个id值,根据这个id查询出name值并且做为传出参数 ~~~ DELIMITER $$ CREATE PROCEDURE `hello`(IN id_in VARCHAR(10),OUT name_out VARCHAR(10)) BEGIN SELECT NAME INTO name_out FROM USER WHERE id=id_in; END$$ DELIMITER ; ~~~ dao层 mode=IN:传入参数,就是`user.id` mode=OUT:传出参数,就是`user.name` StatementType.CALLABLE:说明这是一个存储过程 ~~~ @Select("call hello(#{id,mode=IN,jdbcType=VARCHAR},#{name,mode=OUT,jdbcType=VARCHAR})") @Options(statementType= StatementType.CALLABLE ) public void call(User user); ~~~ service层 ~~~ public void call(){ User user = new User(); user.setId("14"); mybatisDao.call(user); System.out.println(user.getName()); ~~~