mybatis与tk mybatis与pagehelper分页插件

1、看包:

<!--mybatis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.0</version>
</dependency>
<!--tk mybatis-->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
</dependency>
<!--PageHelper分页插件-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.12</version>
</dependency>

2、看配置文件:

mybatis.mapper-locations=classpath:mybatis/mapper/*.xml   
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.username = root
spring.datasource.password = root

3、看实体注解:

@Data    //lombok注解
@Table(name = "tb_student")   //映射表注解
public class Student implements Serializable {
    @Id
    @Column(insertable = false)
//因为用的PGSQL,这里一定要写明查询序列语句,坑点较多
    @GeneratedValue(strategy = GenerationType.IDENTITY,generator = "select nextval('student_id_seq'::regclass)")
    private Integer id;
    private String name;    //如果不使用@Column或者下划线转换等,则需要和数据库字段保持一致
    private String address;
}

4、看通用mapper

public interface MyMapper<T> extends Mapper<T>,InsertListMapper<T> {
   
}

   这里有个坑...,只需要继承就行了,不需要写其他东西,记得别忘了保持泛型

5、看通用service,可选,通用mapper可以直接通过@Autowired直接装配使用了,不过最好定义一个通用service

public interface BaseService<T,TD> {
    void save(T model);//持久化
    void save(List<T> models);//批量持久化
    void deleteById(TD id);//通过主鍵刪除
    void deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4”  //这里有个坑
    void update(T model);//更新
    T findById(TD id);//通过ID查找
    T findBy(String fieldName, Object value) throws TooManyResultsException; //通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束
    List<T> findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4”  //这里有个坑
    List<T> findByCondition(Condition condition);//根据条件查找
    List<T> findAll();//获取所有
}

6、看Service实现

public class AbstractService<T,TD> implements BaseService<T,TD> {
    @Autowired
    private MyMapper<T> mapper;

    private Class<T> clazz;

    public AbstractService(){
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();  //获取超类类型,带泛型
        clazz = (Class<T>) pt.getActualTypeArguments()[0];  //获取泛型类型,就一个泛型,取数组第一个就行了
    }

    @Override
    public void save(T model) {
        mapper.insertSelective(model);
    }

    @Override
    public void save(List<T> models) {
        mapper.insertList(models);
    }

    @Override
    public void deleteById(TD id) {
        mapper.deleteByPrimaryKey(id);
    }

    @Override
    public void deleteByIds(String ids) {
        mapper.deleteByIds(ids);
    }

    @Override
    public void update(T model) {
        mapper.updateByPrimaryKeySelective(model);
    }

    @Override
    public T findById(TD id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public T findBy(String fieldName, Object value) throws TooManyResultsException {
        T model = null;
        try {
            model = clazz.newInstance();   //实例化对象
            Field field = clazz.getDeclaredField(fieldName);   //获取属性
            field.setAccessible(true);  //暴力破解private
            field.set(model, value);   //属性赋值
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
        return mapper.selectOne(model);  //查询
    }

    @Override
    public List<T> findByIds(String ids) {
        return mapper.selectByIds(ids);
    }

    @Override
    public List<T> findByCondition(Condition condition) {
        return mapper.selectByCondition(condition);
    }

    @Override
    public List<T> findAll() {
        return mapper.selectAll();
    }
}

PS:如果是tk.mapper需要获取泛型的话,涉及到了动态代理,需要子类teacherMapper.getClass.getInterfaces()[0].getGenericInterfaces()[0]
//动态代理获取到的class不是teacherMapper,需要先获取接口
//getGenericInterfaces()[0]:获取直接父接口的第一个接口

7、看PageHelper的基本使用

PageHelper.startPage(1,1);  //设置分页数据,该方法之后的第一个select方法会进行分页
PageInfo page = PageInfo.of(service.findAll());  //获得page数据

PS:PageHelper在面对连表查询的时候会出现总记录数错乱,例如A表中的属性包含了N个B表,解决方法是在xml中分表,使用<collection select="" proerty="" column="" ofType="">,select指明查询B表,property表示A表中的List<B>属性,ofType表示B表的javaBean,即List<B>中的泛型B,column表示A表要传到B表的数据,对应A表的数据库字段或者resultMap映射的column字段

8、添加一个bean,摒弃注解扫描mapper

@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
    MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    //自己的mapper位置
    mapperScannerConfigurer.setBasePackage("com.fengwuJ.tkmybatis.mymapper");
    Properties propertiesMapper = new Properties();
    // 通用mapper位置,接口全路径
    propertiesMapper.setProperty("mappers", "com.fengwuJ.tkmybatis.basemapper.MyMapper");
    propertiesMapper.setProperty("notEmpty", "false");
    //主键UUID回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)
    propertiesMapper.setProperty("ORDER", "BEFORE");
    mapperScannerConfigurer.setProperties(propertiesMapper);
    return mapperScannerConfigurer;
}

ps:大写的坑点

插入

SqlServerMapper—>InsertMapperàSqlServerProvideràinsert:

 

INSERT INTO tb_teacher ( name,update_time,is_deleted ) VALUES ( ?,?,? )

直接跳过了id的拼接

 

@Options(

    useGeneratedKeys = true

)

@InsertProvider(

    type = SqlServerProvider.class,

    method = "dynamicSQL"

)

int insert(T var1);

使用@Options(useGeneratedKeys = true) 回显主键

 

@Id:指定主键

@Column:指定数据库查询出来的记录字段(也可以是别名)与实体属性的映射关系,不配置则默认相同名称映射

 

InsertMappeàInsertMapperà BaseInsertProvideràinsert

  1. Id上需添加 @Column(insertable = false)
  2. 使用@Options(useGeneratedKeys = true) 回显主键

 

PS: insertable:默认为true,设置为false时不会拼接该字段

条件查询:

  • Condition查询: 首先,声明一点,Condition也是可以创建Criteria使用java语言创建条件查询的;Condition condition = new Condition(Entity.class); condition.createCriteria().andCondition(“name=”,"呵呵").orCondition()....最后将condition传入selectByExample或者selectByCondition()方法
  • Example查询:首先,也声明一点,Example也是可以通过创建Criteria使用andCondition进行sql拼接查询的;Example example = new Example(Student.class);   Example.Criteria criteria = example.createCriteria();  criteria.andCondition("name like","%和%"); criteria.andEqualTo("age",10);criteria.andLike("name","%和%");条件设置完后,将example传入selectByExample或者selectByCondition()方法即可。
  • 总结:其实这两个查询都是一样,本质上都是通过Criteria进行构建查询条件,继续跟踪源码发现,Example类下有一个List<Example.Criteria> creteria,大多数方法的操作,criteria的派生方法,都是经过一次次转换,通过逻辑判断是and/or、equal/like,最后变成Creteria(String Condition,Object value),被添加到example中的GeneratedCriteria
    内部类的List<Example.Criterion>  
    criteria中。
  • 再说一下,selectByCondition()和selectByExample();condition是Example的子类,selectByExample通过ExampleProvider这个类进行动态解析MappedStatement数据,进行动态拼接sql;Condition底层就是直接调的ExampleProvider;但是这个MappedStatement和Condition以及Example有什么关系,我传入的查询条件与ms怎么映射上的还不得而知

复杂的条件查询(a/b/c)  (d):

  • 第一种方式:要实现以上的结构要么通过weekend.createCriteria,用ctriteria创建三个条件,再用Example创建一个criteria,最后用weekend.and连接,三个以上同理
  • 第二种方式:使用Example创建两个criteria,一个创建三个条件,一个创建一个条件,然后随意选取一个criteria.and(Criteria),三个以上同理
发布了46 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/fengwuJ/article/details/100186175