第一部分:介绍一下mybatis-plus以及她的一些优点
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.1.0version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
第二步:application.yml配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&serverTimezone=CTT
username: root
password: 123456
#输出日志
logging:
level:
root: warn
mp.dao: trace
pattern:
console: "%p%m%n"
mybatis-plus:
# 在classpath前添加星号可以使项目热加载成功
mapper-locations: classpath*:mybatis/**/*Mapper.xml
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
配置文件里的都可以去官网查到具体干嘛的,当然还有很多其他的配置,总之mybatis-plus这么受欢迎是有原因的。
第三步:emmmm,没有第三步下面就可以直接查啦
package mp.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data//之前的博客有讲这个注解
@TableName("user")//指定特定的数据库表,但只要不是差别很大,不用指定也可以
public class User {
//主键
@TableId("id")//用来标识实体类的主键,以便插件在生成主键雪花Id的时候找到哪个是主键。
private String userid;//因为指定了id所所以这名字可以任取,不与数据库id名一样
private String name;
@TableField("role")//当取名不一样可以用这个注解
private String role;
private Date retime;
private Integer age;
/**
* mp排除非表字段的三种方式
* 1:Transient声明的成员变量不参与序列化过程: private Transient String remark;
* 2:如果有序列化要求;设置为静态变量 private static String remark;(但要写getset方法)
* 3: @TableField(exist=false)
*/
//数据库中没有这一条字段,这里只是暂时后台调用这条数据 ,
// private String remark;
}
这个实体类解释的够详细吧
假设我们已存在一张 User 表,且已有对应的实体类 User,实现 User 表的 CRUD 操作我们需要做什么呢?
/** User 对应的 Mapper 接口 */
public interface UserMapper extends BaseMapper<User> { }
对没错,你只需要写一个接口集成BaseMapper这个通用的mapper
// 初始化 User 对象
User user = new User();
// 插入 User (插入成功会自动回写主键到实体类)
user.setName("demo");
result = userMapper.insert(user);
// 更新 User
user.setAge(18);
result = userMapper.updateById(user);
// 查询 User
User exampleUser = userMapper.selectById(user.getId());
// 查询姓名为‘demo’的所有用户记录
List<User> userList = userMapper.selectList(
new EntityWrapper<User>().eq("hero", "demo")
);
// 删除 User
result = userMapper.deleteById(user.getId());
是不是出现了一些新的东西了感觉?什么是eq这就需要你们去官网查了,这是mybatis-plus的条件构造器AbstractWrapper,定义了很多的方法,用到什么去看一看就好了
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
上面的这三种都是mybatis-plus的新特性,lambda调用后面会讲到,支持自动主键生成很强了,有基于facebook的雪花算法也有其他的id类型,这需要你在上面的配置里卖弄配置你想要的id算法,默认好像就是雪花算法,也可以自己设置id。AR模式的话,简单试着用了下,感觉方便还是方便,不过就是一种新的思路理解了。
简单讲一下AR模式吧:
你甚至上面讲的统用mapper都不用实现只需要实体类继承extends Model<>就可以了
package mp.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
@Data
@TableName("test")//指定特定的数据库表,但只要不是差别很大,不用指定也可以
public class Test extends Model<Test> {
//主键
@TableId(type= IdType.UUID)//用来标识实体类的主键,以便插件在生成主键雪花Id的时候找到哪个是主键。//String类型的id
private String id;//因为指定了id所所以这名字可以任取,不与数据库id名一样
private String name;
private Integer age;
}
用测试方法写了curd
package mp;
import mp.entity.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest
@RunWith(SpringRunner.class)
public class ARtest {
//这里类名和test注解重名了所以加test 注解的时候需要详细一点
@org.junit.Test
public void arinsert() {
Test test = new Test();
test.setName("埃及和奶");
test.setAge(90);
boolean flag = test.insert();//AR模式下的curd
System.out.println(flag);
}
@org.junit.Test
public void selectByid() {
Test test = new Test();
Test newTest = test.selectById(123);//返回的是一个新对象
}
@org.junit.Test
public void selectByid2() {
Test test = new Test();
test.setId("123");
Test newTest = test.selectById();//返回的是一个新对象
}
@org.junit.Test
public void updateByid() {
Test test = new Test();
test.setId("123");
test.setName("sdfsdsdf");
test.updateById();//返回的是一个boolean
}
@org.junit.Test
public void deleteByid() {
Test test = new Test();
test.setId("123");
test.deleteById();//返回的是一个boolean
}
}
实体类都有了,下面就在代码里面讲Lambda和其他条件数据库操作吧,耐心吧下面的代码看完,你就知道mybatis-plus是怎么操作数据库的了,代码注释很多,你会看懂的
@Autowired
private UserMapper userMapper;
@Test
public void insert(){
User user = new User();
user.setUserid("00");//可以不设置id,会自动生成
user.setName("向不i哦啊的");
user.setRole("dsa12q d");
user.setRetime(new Date());
int rows = userMapper.insert(user);//返回成功数量
}
private UserMapper userMapper;
查询多个id,返回对象集合
public void selectids(){
List<String> idsList = Arrays.asList("0","5","9");
List<User> userList = userMapper.selectBatchIds(idsList);
userList.forEach(System.out::println);
}
//根据多个条件,查询返回符合条件的所有对象,list集合//map中的键(key)是数据库中的列名不是实体中的属性名
public void selectByMap(){
//map.put("name","顺丰大概");
//map.put("role","dsa12q d");
//这样就类似于where name = "顺丰大概" and role = "dsa12q d"
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("name","顺丰大概");
columnMap.put("role","dsa12q d");
List<User> userList = userMapper.selectByMap(columnMap);
userList.forEach(System.out::println);
}
/**
* 条件构造器:
*名字中含有三,且角色是员工的
* name like ‘%三%’ and age < 40
* queryWrapper.select("id","name")like("name","三").lt("age",40);//这里返回的是这个对象的固定两个字段,返回的还是对象
*/
@Test
public void selectByWrapper(){
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//QueryWrapper继承了AbstraptWrapper
// QueryWrapper query = Wrappers.query();和上面一样。
queryWrapper.like("name","三").lt("age",40);//lt()//默认条件是小于
List<User> userList =userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
/**名字中含有三,且年龄在20和40之间,角色是不为空的
* name like ‘%三%’ and age between 20 and 40 and role is not null
* queryWrapper.like("name","三").between(“age”,20,40).isNotNull(“role”)
*
* 名字为张姓或者年龄大于等于25,按照年龄降序排序,年龄相同按照id升序排列
* name like “张%” or age >=25 order by age desc,id asc;//默认是and如果是or需要.or();
* queryWrapper.likeRight("name","张").or().ge("age",25).orderByDesc("age").orderByAsc("id");
*
* 创建日期是2019年2月11日并且直属上级为名字为王性
* dete_format(create_time,'%y-%m-%d')and manager_id in(select id from user where name like "王%")//子查询就是inSql
* queryWrapper.apply("dete_format(create_time,'%y-%m-%d')={0}","2019-02-11").inSql("manager_id","select id from user where name like "王%"")//
* 上面查时间也有一个 参数的方法,但有可能sql注入的问题(就是sql语句中不小心写了其他(or true or true)查询结果就不对,产生风险)
*
* 名字为王性并且(年龄小于40或邮箱不为空) wq->wq是lomoda表达式
* queryWrapper.likeRight("name","王").and(wq->wq.lt("age",40).or().isNotNull("email"));
*
* 名字为王性或者(年龄小于40并且年龄大于20并且邮箱不为空)
* name like '王%' or (age< 40 and age >20 and email is not null)
* queryWrapper.likeRight("name","王").or(wq->wq.lt("age",40).gt("age".20).isNotNull("email"))
*
* (年龄小于40或者邮箱不为空)并且名字为王性//括号和没有括号不一样。or的优先级小于and的优先级
* (age <40 or email is not null)and name like '王%'
* queryWrapper.nested(wq->wq.ly("age",40).or().isNotNull(email)).likeRight("name","王")
*
* 年龄是31,30,35
* age in (31,30,35)
* queryWrapper.in(“age”,Arrays.asList(31,30,35))
*
* 返回满足条件的一条语句,而不是返回所有满足的结果
* limit 1
* queryWrapper.in(“age”,Arrays.asList(31,30,35)).last("limit 1")
*
* 条件构造器中condition的使用
* 就是当前端传来两个变量要查询的时候,前端可以只输入一个变量也可以查询,condition作为一个条件,如果true就表示这个语句静茹查询条件
* name like ‘%三%’ and age < 40 //以前是先写个判断语句在查询,现在只用一行,就可以是实现
* queryWrapper.like(StringUtils.isNotEmpty(name),"name","name").like(StringUtils.isNotEmpty(email),"email","email");/
*queryWrapper.like(condition,"name","name")//condition来控制where语句加不加入到sql语句中
*
* //实体作为条件构造器构造方法的参数,这样会将user1对象中的所有非空的属性加入sql语句查询,也可以再继续加条件,是互不干扰了,但不要重了
* //当controller中用实体接受前台页面传过来的数据,这样就可以全部或者部分不用写条件,之间对象查找
* QueryWrapper queryWrapper = new QueryWrapper(user1);//QueryWrapper继承了AbstraptWrapper
* List userList =userMapper.selectList(queryWrapper);
*/
}
@Test//lambda条件构造器,防止写错数据库中字段名
public void selectLambda() {
LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();//QueryWrapper继承了AbstraptWrapper
// QueryWrapper query = Wrappers.query();和上面一样。
lambda.like(User::getName, "三").lt(User::getAge, 40);//lt()//默认条件是小于
List<User> userList = userMapper.selectList(lambda);
userList.forEach(System.out::println);
}
//分页查询
@Test
public void selectByPage() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//QueryWrapper继承了AbstraptWrapper
queryWrapper.like("name","三");
Page<User> page = new Page<User>(1,2);
// IPage ipage = userMapper.selectPage(page,queryWrapper);//返回实体
IPage<Map<String,Object>> ipage = userMapper.selectMapsPage(page,queryWrapper);//返回map
System.out.println("总页数:"+ipage.getPages());
System.out.println("总记录数:"+ipage.getTotal());
List<Map<String,Object>> userList = ipage.getRecords();
userList.forEach(System.out::println);
}
public void selectAll() {
LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();//QueryWrapper继承了AbstraptWrapper
lambda.like(User::getName, "三").lt(User::getAge, 40);
List<User> userList =userMapper.selectAll(lambda);
userList.forEach(System.out::println);
public void selectById(){
User user = userMapper.selectById(9);
System.out.println(user);
}
@Test
public void deleteById(){
int rows = userMapper.deleteById("0");
System.out.println(rows);
}
@Test//符合条件都都将会删除
public void deleteByMap(){
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("name","顺丰大概");
columnMap.put("role","dsa12q d");
int rows = userMapper.deleteByMap(columnMap);
}
@Test//同时删除多个记录
public void deleteByds(){
int rows = userMapper.deleteBatchIds(Arrays.asList("5","9"));
System.out.println(rows);
}
@Test//带条件构造器的删除方法
public void deleteByWrapper(){
LambdaQueryWrapper<User> lambdaQuery = Wrappers.<User>lambdaQuery();
lambdaQuery.eq(User::getAge,33).or().gt(User::getAge,47);
int rows = userMapper.delete(lambdaQuery);
System.out.println(rows);
}
}
看到这是不是有点疑问,这怎么和mybatis的完全不一样啊,没有xml,没有配置,上面讲的就是mybatis-plus的新特性,新的查询方法,这就是他官网讲的没有改变只是提高,这就是提高的那一部分,原来mybatis的那样的操作也可以使用,就是原来一样,
以上就是博主一天的学习成果啦,看官网的文档很有帮助,还有就是看baseMapper的源码,按住ctrl点击就可以景区看源码啦,这个框架的源码相对来说还是比较简单易懂的。进阶程序员必备技能,理解源码如果感觉有帮助就点赞鼓励下吧,嘿嘿