MyBatis的优势:
JPA的优势:
MyBatis的劣势:
MP: Mybatis-Plus的出现就是为了解决MyBatis的缺点又能继承它的优点来的;
groupId: com.mp
ArtiafctId: first
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupI>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupI>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupI>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupI>
<artifactId>mybaits-plus-boot-starter</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupI>
<artifactId>mysql-connector-java</artifactId>
</dependency>
在resource的目录下创建application.yml:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp?useSSL=false&Timezone=GMT%2B8
username: root
password: root
创建启动类: com.mp.Application
@SpringBootApplication
@MapperScan("com.mp.dao")
public class Application{
SpringApplication.run(Application.class,args);
}
创建实体类User:com.mp.entity.User
@Data
@ToString
public class User{
//主键
private Long id;
//姓名
private String name;
//年龄
private Integer age;
//邮箱
private String email;
//直属上级
private Long managerId;
//创建时间
private LocalDateTime createTime;
}
创建dao层接口UserMapper: com.mp.dao.UserMapper
public interface UserMapper extends BaseMapper<User>
创建测试类:SimpleTest com.mp.SimpleTest;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SimpleTest{
@Autowried
private UserMapper userMapper;
@Test
public void select(){
List<User>list=userMapper.selectList(null);
Assert.assertEquals(5,list.size());
list.forEach(System.out::println);
}
}
SSM传统编程模式:
通用Mapper
logging:
level:
root: warn
com.mp.dao: trace
pattern:
console: '%p%m%n'
@RunWith(SpringRunner.class)
@SpringBootTest
public class InsertTest{
@Autowried
private UserMapper userMapper;
@Test
public void insert(){
User user=new User();
user.setName("刘明强");
user.setAge(31);
user.setManagerId(1088248166370832385L)
user.setCreateTime(LocalDateTime.now());
int rows.userMapper.insert(user);
System.out.println("影响记录数"+rows);
}
如果属性名与数据库字段一致则无需修改,如果不一致则在括号中给对应的数据库字段名,如下所示:
//加上注解的改变(已在数据库中,将该表名改为mp_user,字段id改为user_id)
@Data
@TableName("mp_user")
public class User{
//主键
@TableId
private Long userId;
@TableField("name");
private String realName;
private Integer age;
private String email;
private Long managerId;
private LocalDateTime createTime;
}
@TableField(exist=false);
private String 属性名;
@SpringBootTest
@RunWith(SpringRunner.class)
public class RetrieveTest{
@Autowired
private UserMapper userMapper;
/**
* 根据Id查询
* /
@Test
public void selectById(){
User user=userMapper.selectById(1094590409767661570L);
System.out.println(user);
}
/**
* 根据Id集合查询
* /
@Test
public void selectIds(){
List idsList=Arrays.asList(10945920410xxx,xxxxx,xxxxx,xxxx);//获取id集合
List userList=userMapper.selectBatchIds(idsList);
userList.forEach(System.out::println);
}
/**
*根据条件查询
*/
@Test
public void selectByMap(){
Map<String,Object> columnMap=new HashMap<>();
// columnMap.put("name","王天风"); //必须与数据库中的对应,如果没有会报错
columnMap.put("age",27); //键是数据库中的列 where age= 27
List<User> userList=userMapper.selectByMap(columnMap);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求: 名字中包含雨并且年龄小于40
* name like '%雨%' and age<40
*/
@Test
public void selectByWrapper1(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.like("name","雨").It("age",40);
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求2: 名字中包含雨并且年龄大于等于20且小于等于40并且email不为空
* name like '%雨%' and age between 20 and 40 and email is not null
*/
@Test
public void selectByWrapper2(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求3: 名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同按照id升序排列;
* name like '王%' or age>= 25 order by age desc,id asc
*/
@Test
public void selectByWrapper3(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.likeRight("name","王").or().ge("age",25).orderByDesc("age").orderByAsc("id");
List<User> userList= userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求4: 创建日期为2019年2月14日并且直属上级为名字为王姓
* data_format(craete_time,'$Y-%m-%d')and manager_id in (select id from user where name like '王%')
*/
@Test
public void selectByWrapper4(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.apply("date_format(create_time,'%Y-%m-%d')=2019-02-14").inSql("manager_id","select id from user where name like '王%'");
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求5: 名字为王姓并且(年龄小于40或邮箱不为空)
* name like '王%' and (age<40 or email is not null)
*/
@Test
public void selectByWrapper5(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.likeRight("name","王").and(wq->wq.It("age",40).or().isNotNull("email"));
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求6: 名字为王姓或者(年龄小于40并且年龄大于20并且邮箱不为空)
* name like '王%' or (age<40 and age>20 and email is not null)
*/
@Test
public void selectByWrapper5(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.likeRight("name","王").or(wq->wq.It("age",40).gt("age",20).isNotNull("email"));
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求7: (年龄小于40或邮箱不为空)并且名字为王姓
* (age<40 or email is not null) and name like '王%'
*/
@Test
public void selectByWrapper7(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.nested(wq.It("age",40).or().isNotNull("email")).likeRight("name","王");
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求8: 年龄为30、31、34、35
* age in (30、31、34、35)
*/
@Test
public void selectByWrapper8(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.in("age",Arrays.asList(30,31,34,35));
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求9:只返回满足条件的其中一条语句即可
* limit 1
*/
@Test
public void selectByWrapper9(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.in("age",Arrays.asList(30,31,34,35)).last("limit 1");
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求10: 名字中包含雨并且年龄小于40 只查询id,name两个字段
* name like '%雨%' and age<40
*/
@Test
public void selectByWrapper10(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.select("id","name").like("name","雨").It("age",40);
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
/**
* 条件构造器查询
* 需求10: 名字中包含雨并且年龄小于40 只查询部分字段使用排除法
* select id,name,age,email from user where like '%雨%' and age<40
*/
@Test
public void selectByWrapper10(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.like("name","雨").It("age",40).select(User.class,info->!info.getColumn().equals("create_time")&&!info.getColumn().equals("manager_id"));
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
}
condition作用:当它的值为true的时候,这个方法才会执行
@Test
public void testCondition(){
String name="王";
String email="";
condition(name,email);
}
private void condition(String name,String email){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
//if(StringUtils.isNotEmpty(name)){
//queryWrapper.like("name",name);
//}
//if(StringUtils.isNotEmpty(email)){
// queryWrapper.like("email",email);
//}
// 下面的写法可以替代上面的这两个
queryWrapper.like(StringUtils.isNotEmpty(name),"name",name).like(StringUtils.isNotEmpty(email),"email",email);
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
实体作为条件构造器构造方法的参数
@Test
public void selectByWrapperEntity(){
User whereUser=new User();
whereUser.setName("刘红雨");
whereUser.setAge(32);
QueryWrapper<User> queryWrapper=new QueryWrapper<User>(whereUser);
queryWrapper.like("name","雨").It("age",40); //这条语句写上,会与whereUser这条同时生效;
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
@Test
public void selectByWrapperAllEq(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
Map<String,Object> params=new HashMap<String,Object>();
params.put("name","王天风");
params.put("age",25);
//queryWrapper.allEq(params);
//过滤查询
queryWrapper.allEq((k,v)!k.equals("name"),params);
List<User> userList=userMapper.selectList(queryWrapper);
userList.forEach(System.out::println);
}
这里allEq就可以加搜索条件
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.select("id","name").like("name","雨").It("age",40);
//使用selectMaps,返回的结果是键值对,即Key为字段名,value为值名;
//使用了select指定了id,name,则返回的只有这两个数据;如果非selectMaps方式,则返回的结果,非id,name的字段会为null,而现在的没有此字段,更好看一点;
List<Map<String.Object>> userList=userMapper.selectMaps(queryWrapper);
userList.forEach(System.out::println);
//使用Lambda来写,会编译时检查User中的字段名是否正确
@Test
public void selectLambda(){
//lambda的创建方式有三种,如下所示:
//LambdaQueryWrapper lambda =new QueryWrapper().lambda;
//LambdaQueryWrapper lambdaQueryWrapper=new LambdaQueryWrapper();
//第三种:
LambdaQueryWrapper<User> lambdaQuery=Wrappers.<User> lambdaQuery();
lambdaQuery.like(User::getName,"雨").It(User::getAge,40);
//where name like '%雨%'
List<User> userList=userMapper.selectList(lambdaQuery);
userList.forEach(System.out::println);
}
@Test
public void selectLambda3(){
List<User> userList=new LambdaQueryChainWrapper<User>(userMapper)
.like(User::getName,"雨").ge)(User::getAge,20).list();
userList.forEach(System.out::println);
}
public interface UserMapper extends BaseMapper<User>{
//使用SQL语句自定义条件 的方法
@Select("select * from user ${ew.customSqlSegment}")
List<User> selectAll(@Param(Constants.WRAPPER)Wrapper<User> wrapper);
}
@Test
public void selectMy(){
LambdaQueryWrapper<User> lambdaQuery =Wrappers<User> lambdaQuery();
lambdaQuery.likeRight(User::getName,"王")
.and(lqw->lqw.It(User::getAge,40).or().isNotNull(User::getEmail));
List<User> userList=userMapper.selectAll(lambdaQuery);
userList.forEach(System.out::println);
}
生成的语句如下:
mybatis-plus:
mapper-locations:
- com/mp/mapper/* # 存放路径
@Configuration
public class MyBatisPlusConfig{
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}
2. 执行查询操作:
@Test
public void selectPage(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.ge("age",26);
Page<User> page=new Page<User>(1,2);
IPage<User> page= userMapper.selectPage(page,queryWrapper);
System.out.println("总页数"+iPage.getPages());
System.out.println("总记录数"+iPage.getTotal());
List<User> userList=iPage.getRecords();
userList.forEach(System.out::println);
}
上面的返回是直接是数据,还有一种方法是返回Map类型的,返回的key为字段名,value为字段值,图示如下:
@Test
public void selectPage(){
QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
queryWrapper.ge("age",26);
Page<User> page=new Page<User>(1,2);
IPag<Map<String,Object>> iPage=userMapper.selectMapsPage(page,queryWrapper);
System.out.println("总页数"+iPage.getPages());
System.out.println("总记录数"+iPage.getTotal());
)}
需要用哪种根据需求而定; 有些场景中只需要查询记录不需要查询总记录数的,我们可以设置Page参数实现只查询一条语句; (平时是两条SQL语句,一条是查询总记录数,一条是查询具体数据的); 下面图示中的Page(long current,long size,boolean isSerchCount) 这个方法中第三个参数如果为false则不查询总记录数
public interface UserMapper extends BaseMapper<User>{
IPage<User> selectUserPage(Page<User> page,@Param(Constants.WRAPPER)Wrapper<User> wrapper);
}
2. XML的形式图示:
3. 测试:
里面演示的是单表的数据,如果需要多表查询的话,则sql语句进行对应的改变即可;
上面是根据ById来进行修改的,如果通过其他的条件来,我们可以使用下面的方式
如果在实体类参数和条件参数都有对一个属性进行定义,那么这两个地方的定义都生效; 在更新少量字段的时候,可以使用set 比如将年龄29改为30 ,图示如下:
链式写法,返回的结果是影响记录数,如果为0则返回false;
- 根据id删除的方法
- 其他普通删除方法
- 以条件构造器为参数的删除方法
这条语句的含义是会先去查询数据库中是否有已经存在的记录,如果有的话则进行修改update操作,如果没有记录则进行insert 增加操作;
如果全局策略和局部策略都设置了,那么局部策略生效,它是优先于全局策略的;设置什么样的策略更为合适则最好是依据实际情况来进行判定;
内容:
基本配置:
ConfigLocation:
实际操作:
mapperLocations
实际操作:
Maven 多模块项目的扫描路径需以classpath*: 开头(即加载多个jar包下的XML文件)
其他的配置可以找官网上有,这里提到的是经常用的;
这个可以不用配置,它可以根据url获取数据库的类型
这里有几种策略,比如忽略"" 空字符串,null,等;也可以对给默认null值等;需要使用的请单独详细了解;
它里面的一些方法和通用Mapper的方法有些事不一样的,具体请直接进入源码查看