
mybatis-plus中baseMapper、ServiceImpl、IService的理解整理
mybatis的使用姿势
整体结构图
忽略数据库连接配置,简单的步骤如下:
从domain出发(或者称为do),定义和数据库表对应的实体类。
再到mapper层(或者称为dao)。定义mapper接口,通过xml方式或者注解方式书写与数据库交互的语句。(SQL存在的地方)
再到service层。通过依赖注入mapper接口,实现调用。
mybatis-plus的使用姿势
从domain出发(或者称为do),定义和数据库表对应的实体类。
使用
@TableName
注解,和数据库表进行绑定。还有@TableId用于指定表中的主键字段、@TableField用于指定表中的非主键字段等等。
再到mapper层(或者称为dao)。
这里的mapper接口,或者dao接口,直接继承
BaseMapper<>
接口。(也可以自定义很多方法)BaseMapper<>
接口包含了常规增删查改操作此时,可以通过dao接口,使用基本的增删查改操作。在其他地方依赖注入即可。但是按遵循规范啊
再到service层。
service接口继承
ISevice
接口。serviceImpl实现类继承
ServiceImpl<>
类,同时实现service接口。此时,可以在serviceImpl使用大量Mp内置的增删查改方法了。
do层
package com.mpdemo.mpdemo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName(value = "user")
public class User {
/**
* 用户id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 注册手机号
*/
private String phone;
/**
* 详细信息
*/
private String info;
/**
* 使用状态(1正常 2冻结)
*/
private Integer status;
/**
* 账户余额
*/
private Integer balance;
}
dao层
在dao层(或mapper层)
当我们实现BaseMapper
的时候,MP就会帮我们把BaseMapper里的接口类全部实现代理,成为可以直接被我们调用的类,这个过程完全不需要我们去写xml,当然我们也可以在接口中写上我们自己自定义的方法,但是我们自定义的方法必须去写xml去映射方法(或者注解SQL),默认他会去扫描resources下的mapper文件夹下的xml。
因此BaseMapper就是帮我们写了很多的基本方法。
dao接口继承BaseMapper
@Mapper
public interface UserDao extends BaseMapper<User> {
}
public interface BaseMapper<T> extends Mapper<T> {
int insert(T entity);
int deleteById(Serializable id);
int deleteByMap(@Param("cm") Map<String, Object> columnMap);
int delete(@Param("ew") Wrapper<T> queryWrapper);
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
int updateById(@Param("et") T entity);
int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
T selectById(Serializable id);
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
T selectOne(@Param("ew") Wrapper<T> queryWrapper);
Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
<E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
}
当dao接口继承BaseMapper<T>以后,在其他地方通过依赖注入dao,就可以使用增删查改操作了。
service层
接下来就是说IService
接口和ServiceImpl,
其实这两个类的存在也是很合理的,你想MP帮我们去实现了mapper
接口,那mapper
接口是不是得有Service
接口和一个Service
实现类啊?所以他其实帮我们连实现类也写好了,我们只需要去实现接口和继承实现类就好了。当然Service
接口中我们也可以写自己的自定义方法但是同时我们也需要在ServiceImpl
中自己去写我们自定义的方法,而从IService
接口中实现的方法呢?ServiceImp
l其实已经帮我们实现了,我们只要继承他就可以了。
注意,这里IUserService、IService不是必须的啊,ServiceImpl<>
也继承了IService
。我们自己也写一个是为了分层解耦,为了规范!
UserServiceImpl也可以不实现我们自己定义的IUserService接口,继承ServiceImpl<UserDao, User>即可。
public interface IUserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements IService<User> {
}
可以看到系统提供的这个ServiceImpl
类中有一个成员变量,他被@Autowired
注解修饰也就是说这个成员变量是自动注入的,可以发现他的名字叫baseMapper
,我们那个UserDao
是继承自baseMapper
的吧,所以我们把那个接口传进来,其实就是让这个实现类去自动注入我们的那个UserDao
。
因此,在UserServiceImpl
可以使用baseMapper
,实现一些自定义的方法。例如
@Repository
public class ArticleDao extends ServiceImpl<ArticleMapper, ArticleDO> {
/**
* ArticlePayRecordMapper 继承的 BaseMapper<ArticlePayRecordDO>
* 因此可以直接使用baseMapper中的通用方法
* 重新使用@Resource注入,则可以使用ArticleMapper自定义的方法
*/
@Resource
private ArticleDetailMapper articleDetailMapper;
@Resource
private ReadCountMapper readCountMapper;
@Resource
private ArticleMapper articleMapper;
public ArticleDTO queryArticleDetail(Long articleId) {
// 查询文章记录
ArticleDO article = baseMapper.selectById(articleId);
if (article == null || Objects.equals(article.getDeleted(), YesOrNoEnum.YES.getCode())) {
return null;
}
// 查询文章正文
ArticleDTO dto = ArticleConverter.toDto(article);
if (showReviewContent(article)) {
ArticleDetailDO detail = findLatestDetail(articleId);
dto.setContent(detail.getContent());
} else {
// 对于审核中的文章,只有作者本人才能看到原文
dto.setContent("### 文章审核中,请稍后再看");
}
return dto;
}
这里baseMapper
就是ArticleMapper
,使用baseMapper
可以调用常规的方法。
但是,如果需要使用ArticleMapper
中自定义的方法,那就需要再次注入ArticleMapper
了。
- 感谢你赐予我前进的力量