当前位置: 首页>编程语言>正文

springboot mybatis 跨库查询 mybatis可以跨库查询吗

项目开发的过程中,碰到一个需求,要求是:用户完成任务后,会获得积分,需要展示跟任务积分差不多的积分商品列表.
中间用到了两个之前技术点:

1.跨库查询

2.排序

①跨库查询

先说跨库查询,因为项目使用的是springcloud框架,分为了3个部分,一是核心业务(designer),二是核心业务的总控后台(mbg),三是商城项目(mall),需要展示的积分商品是存在mall对应的数据库中,但该业务是属于designer的,所以使用了跨库查询,数据库为mysql,跨库查询的核心点:
因为是mybatis和springmvc,所以代码编写过程是按照service->dao->xml的顺序来进行的
首先要先在config文件中配置自己所要跨的库名:

#商城库名
myConfig.mallDb=mall_test

接下来要在java中引用配置好的库名:

@Component
@ConfigurationProperties(prefix = "myConfig")
public class UserSignPoint {

    /**
     * 商城库名
     */
    private String mallDb;

    public String getMallDb() {
        return mallDb;
    }

    public void setMallDb(String mallDb) {
        this.mallDb = mallDb;
    }
}

@Component注解:
把普通pojo实例化到spring容器中,当我们的类不属于各种归类的时候(不属于@Controller、@Services等的时候),我们就可以使用@Component来标注这个类
@ConfigurationProperties(prefix = “myConfig”)注解:
是Spring Boot中的标签,简单点说它可以让开发者将整个配置文件,映射到对象中.
这样spring容器初始化UserSignPoint类时,就会把配置文件中的mallDb对应的库名映射到实体类的属性中.
接下来就是在service层写具体的业务逻辑,这里跳过不说,
直接进入到dao层,这里需要注意的点是@Param注解.
这个注解作用主要是传递参数,当只有一个参数,且在sql中使用的是

#{param}

,可以省略不写,但如果使用的是

${param}

时,是必须要写的.#{param}和${param}的区别:#号是相当于传递参数,简单点来说是在sql中给要传递过去的参数自动添加"",而?则是拼接sql用的,所以在xml文件中就使用

${mallDb}.goods_master

这样来实现跨库查询

②排序

在完成项目的过程中,出现了一个问题,如下图:

有一个分享的消息,点开后展示的是跟获得积分最接近的4个商品数据,本来以为挺简单的一个功能,后来发现存在一些问题,在db中的商品数据,积分和价格并不是固定的,部分商品是通过设定的比例来确定的,所以只能先查询出所有的数据,然后再java中去进行计算,接下来就是重点了.

我需要拿到4个跟完成任务获得积分相近的4条数据,于是我在VO的实体类中新增了一个字段,用来存积分商品-任务积分的绝对值,然后通过这个绝对值进行升序排列,从头取4个即可完成需求,因为是对象排序,太久没写有些忘了,所以去网上找了相关的方法,发现有两种方法来完成:

1.Collections.sort(List list)

2.Collections.sort(List list,Comparator c)

第一种,概括来说称为自然排序,参与排序的对象需实现comparable接口,重写其compareTo()方法,方法体中实现对象的比较大小规则,也就是在实体类里重写compareTo的方法.

但第一种耦合高,并且不够灵活,所以通常采用第二种方法

第二种,是创建一个comparator的比较器(匿名内部类),然后重写compareTo的方法,就可以实现排序了.

去网上找了一下相关的源码资料,大概总结了一下整个过程(第二种方法):

首先

Collections.sort(strings);
//跟踪进入源码
public static <T> void sort(List<T> list, Comparator<? super T> c) {
        list.sort(c);//发现了这个方法,c就是一个比较器
    }
//进一步跟进代码
default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);//把之前的集合转成一个obj数组,c是比较器
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }
//再追踪代码
public static <T> void sort(T[] a, Comparator<? super T> c) {
        //c==null,就是不采用比较器,直接自然排序
        if (c == null) {
            sort(a);
        } else {
            //老的归并排序,不用管了现在默认是false
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a, c);
            else
                TimSort.sort(a, 0, a.length, c, null, 0, 0);
        }
    }
//接下来先看c==null的情况
public static void sort(Object[] a) {
        //依旧不用管
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
            //走else,看的出来走的是Timsort的sort方法
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }
//再进入
//a数组,lo数组最小长度0,hi最大长度,剩余的不重要
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
        //assert验证相当于if(true)
        assert a != null && lo >= 0 && lo <= hi && hi <= a.length;
        //数组长度
        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        //当数组大小小于MIN_MERGE(32)的时候,就用一个"mini-TimSort"的方法排序,jdk1.7新加
        if (nRemaining < MIN_MERGE) {
            //将我们最长的递减序列,找出来,然后倒过来(这个方法看不懂)
            int initRunLen = countRunAndMakeAscending(a, lo, hi);
            //二进制排序
            binarySort(a, lo, hi, lo + initRunLen);
            return;
        }

        //先扫描一次array,找到已经排好的序列,然后再用刚才的mini-TimSort,然后合并,这就是TimSort的核心思想
        ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
        int minRun = minRunLength(nRemaining);
        do {
            // Identify next run
            //该值最终范围为 16 <= k <= 32之间
            int runLen = countRunAndMakeAscending(a, lo, hi);

            // If run is short, extend to min(minRun, nRemaining)
            //该处为什么要判断?该判断主要为了确认,在该排序的子数组中,是否包含了无序排列
            // 如果runLen == mainRun的时候,就说明数组中的所有元素都处于有序状态
            if (runLen < minRun) {
                int force = nRemaining <= minRun ? nRemaining : minRun;
                 // 排序, 在该处中,lo是开始索引,force为有序数组的长度,所以lo+runLen为实际开始排序的元素的索引
                // 而 lo + force 确认了当次排序的范围
                binarySort(a, lo, lo + force, lo + runLen);
                runLen = force;
            }

            // Push run onto pending-run stack, and maybe merge
            ts.pushRun(lo, runLen);
            ts.mergeCollapse();

            // Advance to find next run
            lo += runLen;
            nRemaining -= runLen;
        } while (nRemaining != 0);

        // Merge all remaining runs to complete sort
        assert lo == hi;
        ts.mergeForceCollapse();
        assert ts.stackSize == 1;
    }
//回到c!=null时的情况
//源码走的是
 TimSort.sort(a, 0, a.length, c, null, 0, 0);
//进入代码
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                         T[] work, int workBase, int workLen) {
        assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;

        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
            binarySort(a, lo, hi, lo + initRunLen, c);
            return;
        }

        //有比较器的时候主要是这个地方的源码不一样,
        //没有比较器的时候用的是ComparableTimSort这个来进行下面的比较操作的,而用了比较器之后则是直接通过TimSort这个来进行比较的,其余地方的代码都是一样的.
        TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
        int minRun = minRunLength(nRemaining);
        do {
            // Identify next run
            int runLen = countRunAndMakeAscending(a, lo, hi, c);

            // If run is short, extend to min(minRun, nRemaining)
            if (runLen < minRun) {
                int force = nRemaining <= minRun ? nRemaining : minRun;
                binarySort(a, lo, lo + force, lo + runLen, c);
                runLen = force;
            }

            // Push run onto pending-run stack, and maybe merge
            ts.pushRun(lo, runLen);
            ts.mergeCollapse();

            // Advance to find next run
            lo += runLen;
            nRemaining -= runLen;
        } while (nRemaining != 0);

        // Merge all remaining runs to complete sort
        assert lo == hi;
        ts.mergeForceCollapse();
        assert ts.stackSize == 1;
    }

通过看源码可以看出,Collections.sort方法有没有比较器,底层实现都是TimSort实现的,TimSort算法就是找到已经排好序数据的子序列,然后对剩余部分排序,然后合并起来.
在写排序的过程中,发现了jdk1.8可以简化代码

Collections.sort(hotGoodsList, new Comparator<HotGoods>() {
    @Override
    public int compare(HotGoods o1, HotGoods o2) {
        return o1.getGoodsScore().compareTo(o2.getGoodsScore());
    }
});
//可以直接替换成
hotGoodsList.sort(Comparator.comparing(HotGoods::getGoodsScore));



https://www.xamrdz.com/lan/5wx1944429.html

相关文章: