对象关系映射模型Hibernate。用来实现非常轻量级的对象的封装。将对象与数据库建立映射关系。实现增删查改。 MyBatis与Hibernate非常相似。对象关系映射模型ORG。java对象与关系数据库映射的模型。
1 配置MyBatis 最佳实践 最佳实战: ● 引入mybatis-starter ● 配置application.yaml中,指定mapper-location位置即可 ● 编写Mapper接口并标注@Mapper注解 ● 简单方法直接注解方式 ● 复杂方法编写mapper.xml进行绑定映射 ● @MapperScan(“com.atguigu.admin.mapper”) 简化,其他的接口就可以不用标注@Mapper注解
添加MyBatis依赖 1 2 3 4 5 6 7 8 9 10 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
配置数据库连接 在application.properties中配置mysql的链接配置
1 2 3 4 spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
创建数据表 1 2 3 4 5 6 CREATE TABLE `User ` ( `id` bigint NOT NULL AUTO_INCREMENT, `name` varchar (100 ) COLLATE utf8mb4_general_ci DEFAULT NULL , `age` int DEFAULT NULL , PRIMARY KEY (`id`) ) ENGINE= InnoDB DEFAULT CHARSET= utf8mb4 COLLATE = utf8mb4_general_ci
创建java对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Data @NoArgsConstructor public class User { private Long id; private String name; private Integer age; public User (String name, Integer age) { this .name = name; this .age = age; } }
MyBatis参数传递 使用@Param参数传递
1 2 @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})") int insert(@Param("name") String name, @Param("age") Integer age);
使用map 传递参数
1 2 3 4 5 6 7 @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER})") int insertByMap(Map<String, Object> map); //调用 Map<String, Object> map = new HashMap<>(); map.put("name", "CCC"); map.put("age", 40); userMapper.insertByMap(map);
使用普通java对象
1 2 @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})") int insertByUser(User user);
2注解模式 创建数据表的操作接口 1 2 3 4 5 6 7 8 9 10 @Mapper public interface UserMapper { @Select("SELECT * FROM USER WHERE NAME = #{name}") User findByName (@Param("name") String name) ; @Insert("INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age})") int insert (@Param("name") String name, @Param("age") Integer age) ; }
增删改查操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public interface UserMapper { @Select("SELECT * FROM user WHERE name = #{name}") User findByName (@Param("name") String name) ; @Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})") int insert (@Param("name") String name, @Param("age") Integer age) ; @Update("UPDATE user SET age=#{age} WHERE name=#{name}") void update (User user) ; @Delete("DELETE FROM user WHERE id =#{id}") void delete (Long 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 @Transactional @RunWith(SpringRunner.class) @SpringBootTest public class ApplicationTests { @Autowired private UserMapper userMapper; @Test @Rollback public void testUserMapper () throws Exception { userMapper.insert("AAA" , 20 ); User u = userMapper.findByName("AAA" ); Assert.assertEquals(20 , u.getAge().intValue()); u.setAge(30 ); userMapper.update(u); u = userMapper.findByName("AAA" ); Assert.assertEquals(30 , u.getAge().intValue()); userMapper.delete(u.getId()); u = userMapper.findByName("AAA" ); Assert.assertEquals(null , u); } }
3 XML方式 创建Mapper文件 在应用主类中增加mapper的扫描包配置:
1 2 3 4 5 6 7 8 9 @MapperScan("com.didispace.chapter36.mapper") @SpringBootApplication public class Chapter36Application { public static void main(String[] args) { SpringApplication.run(Chapter36Application.class, args); } }
Mapper包下创建User表
1 2 3 4 5 6 7 public interface UserMapper { User findByName(@Param("name") String name); int insert(@Param("name") String name, @Param("age") Integer age); }
在配置文件中通过mybatis.mapper-locations参数指定xml配置的位置
1 mybatis.mapper-locations=classpath:mapper/*.xml
xml配置目录下创建User表的mapper配置
1 2 3 4 5 6 7 8 9 10 11 12 13 <?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.didispace.chapter36.mapper.UserMapper"> <select id="findByName" resultType="com.didispace.chapter36.entity.User"> SELECT * FROM USER WHERE NAME = #{name} </select> <insert id="insert"> INSERT INTO USER(NAME, AGE) VALUES(#{name}, #{age}) </insert> </mapper>
对xml方式进行调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Slf4j @RunWith(SpringRunner.class) @SpringBootTest @Transactional public class Chapter36ApplicationTests { @Autowired private UserMapper userMapper; @Test @Rollback public void test() throws Exception { userMapper.insert("AAA", 20); User u = userMapper.findByName("AAA"); Assert.assertEquals(20, u.getAge().intValue()); } }
4 MyBatis-Plus 什么是MyBatis-Plus MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 mybatis plus 官网 建议安装 MybatisX 插件
通用Mapper能力
增强单表查询能力
多种主键策略,支持UUID和雪花算法
基础代码生成器
乐观锁
引入 1 2 3 4 5 <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.4.1</version > </dependency >
自动配置 ● MybatisPlusAutoConfiguration 配置类,MybatisPlusProperties 配置项绑定。mybatis-plus:xxx 就是对mybatis-plus的定制 ● SqlSessionFactory 自动配置好。底层是容器中默认的数据源 ● mapperLocations 自动配置好的。有默认值。classpath*:/mapper/**/*.xml;任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件。 建议以后sql映射文件,放在 mapper下 ● 容器中也自动配置好了 SqlSessionTemplate ● @Mapper 标注的接口也会被自动扫描;建议直接 @MapperScan(“com.atguigu.admin.mapper”) 批量扫描就行
优点 优点: ● 只需要我们的Mapper继承 BaseMapper 就可以拥有crud能力
进阶操作
设置表明和自增主键
使用条件构造器
boolean condition表示该条件是否 加入最后生成的sql中
支持多种条件表达式拼接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 AbstractWrapper allEq eq ne gt ge lt le between notBetween like notLike likeLeft likeRight notLikeLeft notLikeRight isNull isNotNull in notIn inSql notInSql groupBy orderByAsc orderByDesc orderBy having func or and nested apply last exists notExists QueryWrapper select UpdateWrapper set setSql lambda
CRUD实例 DAO层
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 public interface ArticleMapper extends BaseMapper <Article> {} public interface BaseMapper <T> extends Mapper <T> { int insert (T entity) ; int deleteById (Serializable id) ; int deleteById (T entity) ; default int deleteByMap (Map<String, Object> columnMap) { return this .delete((Wrapper)Wrappers.query().allEq(columnMap)); } int delete (@Param("ew") Wrapper<T> queryWrapper) ; int deleteBatchIds (@Param("coll") Collection<?> idList) ; int updateById (@Param("et") T entity) ; int update (@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper) ; default int update (@Param("ew") Wrapper<T> updateWrapper) { return this .update((Object)null , updateWrapper); } T selectById (Serializable id) ; List<T> selectBatchIds (@Param("coll") Collection<? extends Serializable> idList) ; void selectBatchIds (@Param("coll") Collection<? extends Serializable> idList, ResultHandler<T> resultHandler) ; default List<T> selectByMap (Map<String, Object> columnMap) { return this .selectList((Wrapper)Wrappers.query().allEq(columnMap)); } default void selectByMap (Map<String, Object> columnMap, ResultHandler<T> resultHandler) { this .selectList((Wrapper)Wrappers.query().allEq(columnMap), resultHandler); } default T selectOne (@Param("ew") Wrapper<T> queryWrapper) { return this .selectOne(queryWrapper, true ); } default T selectOne (@Param("ew") Wrapper<T> queryWrapper, boolean throwEx) { List<T> list = this .selectList(queryWrapper); int size = list.size(); if (size == 1 ) { return list.get(0 ); } else if (size > 1 ) { if (throwEx) { throw new TooManyResultsException ("Expected one result (or null) to be returned by selectOne(), but found: " + size); } else { return list.get(0 ); } } else { return null ; } } default boolean exists (Wrapper<T> queryWrapper) { Long count = this .selectCount(queryWrapper); return null != count && count > 0L ; } Long selectCount (@Param("ew") Wrapper<T> queryWrapper) ; List<T> selectList (@Param("ew") Wrapper<T> queryWrapper) ; void selectList (@Param("ew") Wrapper<T> queryWrapper, ResultHandler<T> resultHandler) ; List<T> selectList (IPage<T> page, @Param("ew") Wrapper<T> queryWrapper) ; void selectList (IPage<T> page, @Param("ew") Wrapper<T> queryWrapper, ResultHandler<T> resultHandler) ; List<Map<String, Object>> selectMaps (@Param("ew") Wrapper<T> queryWrapper) ; void selectMaps (@Param("ew") Wrapper<T> queryWrapper, ResultHandler<Map<String, Object>> resultHandler) ; List<Map<String, Object>> selectMaps (IPage<? extends Map<String, Object>> page, @Param("ew") Wrapper<T> queryWrapper) ; void selectMaps (IPage<? extends Map<String, Object>> page, @Param("ew") Wrapper<T> queryWrapper, ResultHandler<Map<String, Object>> resultHandler) ; <E> List<E> selectObjs (@Param("ew") Wrapper<T> queryWrapper) ; <E> void selectObjs (@Param("ew") Wrapper<T> queryWrapper, ResultHandler<E> resultHandler) ; default <P extends IPage <T>> P selectPage (P page, @Param("ew") Wrapper<T> queryWrapper) { page.setRecords(this .selectList(page, queryWrapper)); return page; } default <P extends IPage <Map<String, Object>>> P selectMapsPage (P page, @Param("ew") Wrapper<T> queryWrapper) { page.setRecords(this .selectMaps(page, queryWrapper)); return page; } }
Service层 1 2 3 4 5 6 7 8 9 @Service public class UserServiceImpl extends ServiceImpl <UserMapper,User> implements UserService {} public interface UserService extends IService <User> {}
完整实例 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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 package com.baomidou.mybatisplus.samples.crud;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.core.toolkit.Wrappers;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.samples.crud.entity.User;import com.baomidou.mybatisplus.samples.crud.entity.User2;import com.baomidou.mybatisplus.samples.crud.mapper.User2Mapper;import com.baomidou.mybatisplus.samples.crud.mapper.UserMapper;import org.junit.jupiter.api.Assertions;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import java.util.Map;import static org.assertj.core.api.Assertions.assertThat;@SpringBootTest public class CrudTest { @Autowired private UserMapper mapper; @Autowired private User2Mapper user2Mapper; @Test public void aInsert () { User user = new User (); user.setName("小羊" ); user.setAge(3 ); user.setEmail("abc@mp.com" ); assertThat(mapper.insert(user)).isGreaterThan(0 ); assertThat(user.getId()).isNotNull(); } @Test public void bDelete () { assertThat(mapper.deleteById(3L )).isGreaterThan(0 ); assertThat(mapper.delete(new QueryWrapper <User>() .lambda().eq(User::getName, "Sandy" ))).isGreaterThan(0 ); } @Test public void cUpdate () { assertThat(mapper.updateById(new User ().setId(1L ).setEmail("ab@c.c" ))).isGreaterThan(0 ); assertThat( mapper.update( new User ().setName("mp" ), Wrappers.<User>lambdaUpdate() .set(User::getAge, 3 ) .eq(User::getId, 2 ) ) ).isGreaterThan(0 ); User user = mapper.selectById(2 ); assertThat(user.getAge()).isEqualTo(3 ); assertThat(user.getName()).isEqualTo("mp" ); mapper.update( null , Wrappers.<User>lambdaUpdate().set(User::getEmail, null ).eq(User::getId, 2 ) ); assertThat(mapper.selectById(1 ).getEmail()).isEqualTo("ab@c.c" ); user = mapper.selectById(2 ); assertThat(user.getEmail()).isNull(); assertThat(user.getName()).isEqualTo("mp" ); mapper.update( new User ().setEmail("miemie@baomidou.com" ), new QueryWrapper <User>() .lambda().eq(User::getId, 2 ) ); user = mapper.selectById(2 ); assertThat(user.getEmail()).isEqualTo("miemie@baomidou.com" ); mapper.update( new User ().setEmail("miemie2@baomidou.com" ), Wrappers.<User>lambdaUpdate() .set(User::getAge, null ) .eq(User::getId, 2 ) ); user = mapper.selectById(2 ); assertThat(user.getEmail()).isEqualTo("miemie2@baomidou.com" ); assertThat(user.getAge()).isNull(); } @Test public void dSelect () { mapper.insert( new User ().setId(10086L ) .setName("miemie" ) .setEmail("miemie@baomidou.com" ) .setAge(3 )); assertThat(mapper.selectById(10086L ).getEmail()).isEqualTo("miemie@baomidou.com" ); User user = mapper.selectOne(new QueryWrapper <User>().lambda().eq(User::getId, 10086 )); assertThat(user.getName()).isEqualTo("miemie" ); assertThat(user.getAge()).isEqualTo(3 ); mapper.selectList(Wrappers.<User>lambdaQuery().select(User::getId)) .forEach(x -> { assertThat(x.getId()).isNotNull(); assertThat(x.getEmail()).isNull(); assertThat(x.getName()).isNull(); assertThat(x.getAge()).isNull(); }); mapper.selectList(new QueryWrapper <User>().select("id" , "name" )) .forEach(x -> { assertThat(x.getId()).isNotNull(); assertThat(x.getEmail()).isNull(); assertThat(x.getName()).isNotNull(); assertThat(x.getAge()).isNull(); }); } @Test public void orderBy () { List<User> users = mapper.selectList(Wrappers.<User>query().orderByAsc("age" )); assertThat(users).isNotEmpty(); List<User> users2 = mapper.selectList(Wrappers.<User>query().orderByAsc("age" , "name" )); assertThat(users2).isNotEmpty(); List<User> users3 = mapper.selectList(Wrappers.<User>query().orderByAsc("age" ).orderByDesc("name" )); assertThat(users3).isNotEmpty(); } @Test public void selectMaps () { List<Map<String, Object>> mapList = mapper.selectMaps(Wrappers.<User>query().orderByAsc("age" )); assertThat(mapList).isNotEmpty(); assertThat(mapList.get(0 )).isNotEmpty(); System.out.println(mapList.get(0 )); } @Test public void selectMapsPage () { IPage<Map<String, Object>> page = mapper.selectMapsPage(new Page <>(1 , 5 ), Wrappers.<User>query().orderByAsc("age" )); assertThat(page).isNotNull(); assertThat(page.getRecords()).isNotEmpty(); assertThat(page.getRecords().get(0 )).isNotEmpty(); System.out.println(page.getRecords().get(0 )); } @Test public void orderByLambda () { List<User> users = mapper.selectList(Wrappers.<User>lambdaQuery().orderByAsc(User::getAge)); assertThat(users).isNotEmpty(); List<User> users2 = mapper.selectList(Wrappers.<User>lambdaQuery().orderByAsc(User::getAge, User::getName)); assertThat(users2).isNotEmpty(); List<User> users3 = mapper.selectList(Wrappers.<User>lambdaQuery().orderByAsc(User::getAge).orderByDesc(User::getName)); assertThat(users3).isNotEmpty(); } @Test public void testSelectMaxId () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.select("max(id) as id" ); User user = mapper.selectOne(wrapper); System.out.println("maxId=" + user.getId()); List<User> users = mapper.selectList(Wrappers.<User>lambdaQuery().orderByDesc(User::getId)); Assertions.assertEquals(user.getId().longValue(), users.get(0 ).getId().longValue()); } @Test public void testGroup () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.select("age, count(*)" ) .groupBy("age" ); List<Map<String, Object>> maplist = mapper.selectMaps(wrapper); for (Map<String, Object> mp : maplist) { System.out.println(mp); } LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper <User>().lambda() .select(User::getAge) .groupBy(User::getAge) .orderByAsc(User::getAge); for (User user : mapper.selectList(lambdaQueryWrapper)) { System.out.println(user); } } @Test public void testTableFieldExistFalse () { QueryWrapper<User> wrapper = new QueryWrapper <>(); wrapper.select("age, count(age) as count" ) .groupBy("age" ); List<User> list = mapper.selectList(wrapper); list.forEach(System.out::println); list.forEach(x -> { Assertions.assertNull(x.getId()); Assertions.assertNotNull(x.getAge()); Assertions.assertNotNull(x.getCount()); }); mapper.insert( new User ().setId(10088L ) .setName("miemie" ) .setEmail("miemie@baomidou.com" ) .setAge(3 )); User miemie = mapper.selectById(10088L ); Assertions.assertNotNull(miemie); } @Test public void testSqlCondition () { Assertions.assertEquals(user2Mapper.selectList(Wrappers.<User2>query() .setEntity(new User2 ().setName("n" ))).size(), 2 ); Assertions.assertEquals(user2Mapper.selectList(Wrappers.<User2>query().like("name" , "J" )).size(), 2 ); Assertions.assertEquals(user2Mapper.selectList(Wrappers.<User2>query().gt("age" , 18 ) .setEntity(new User2 ().setName("J" ))).size(), 1 ); } }