1 Star 6 Fork 0

Createsequence / mybatis-plus-join

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

一、简介

本项目基于 mybatis-plus,提供通过条件构造器以代码方式构造 join 查询的相关功能。

开发的初衷是为了解决mp日常使用中感觉到的一些痛点的,比如条件构造器不支持join语法,lambda表达式版本的group...having支持不够、查询字段与条件字段都不支持数据库函数,不支持逻辑表,像in或eq这类的方法需要重复添加判空条件......等等。

本框架旨保留mp原功能的基础上,基于Wrapper类扩展一个新的JoinWrapper以在不修改已有代码的基础上支持上述功能。

maven-central

二、快速开始

  1. 引入 mybatis-plus-boot-starter 与 mybatis-plus-join 依赖:

    <dependency>
        <groupId>top.xiajibagao</groupId>
        <artifactId>mybatis-plus-join</artifactId>
        <version>${version}</version>
    </dependency>
    
    <depeendency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>${mybatis-plus.version}</version>
    </depeendency>

    本项目需要自行引入依赖 mybatis-plus-boot-starter,此外其他依赖皆不向下传递

  2. 将动态返回值插件DynamicResultInterceptor注册到 com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean 中 ,

  3. 然后将扩展 SQL 注入器 JoinMethodInjector注入到 com.baomidou.mybatisplus.core.config.GlobalConfig中。

    这里给出一个最简单配置:

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
    
        // 注册动态返回值插件
        sqlSessionFactory.setPlugins(new DynamicResultInterceptor());
    
        // 注册扩展sql注入器
        MybatisConfiguration configuration = new MybatisConfiguration();
        GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
        globalConfig.setSqlInjector(new JoinMethodInjector());
        sqlSessionFactory.setConfiguration(configuration);
    
        return sqlSessionFactory.getObject();
    }
  4. mapper接口从继承 mp 提供的 BaseMapper换为 JoinMapper

    @Mapper
    public interface StudentMapper<T> extend JoinMapper<T> {
        // ... ...
    }
  5. 使用 JoinWrapper 构建查询条件,并使用 JoinMapper 提供的方法进行查询

    JoinWrapper<Student, StudentVO> wrapper = JoinWrapper.create(Student.class, StudentVO.class)
        .selectAll() // 查询 Foo 的全部字段
        .leftJoin(Score.class) // 关联查询 Score
        .on(StudentDO::getId, Condition.EQ, Score::getStudentId)
        .selectAll(); // 查询 Score 的全部字段
    List<StudentVO> StudentVOS = StudentMapper.selectListJoin(wrapper);

三、核心功能

分别创建学生表 student,课程表 course 与考试分数表 score 三张表,其对应数据库脚本如下:

-- 课程表
CREATE TABLE `course`  (
    `id` int(0) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
    `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
    PRIMARY KEY (`id`) USING BTREE
)

-- 考试分数表
CREATE TABLE `score`  (
    `id` int(0) NOT NULL AUTO_INCREMENT,
    `student_id` int(0) NULL DEFAULT NULL,
    `course_id` int(0) NULL DEFAULT NULL,
    `score` int(0) NULL DEFAULT NULL,
    PRIMARY KEY (`id`) USING BTREE
)

-- 学生表
CREATE TABLE `student`  (
    `id` int(0) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
    PRIMARY KEY (`id`) USING BTREE
)

以下示例皆基于上述三表及对应实体。

1、字段别名

条件构造器可以指定主表与可以指定对象类型,需要指定返回值对象类型,并指定别名:

// 查询学生id,学生名称并指定别名,其余与默认字段相同
JoinWrapper<StudentDO, StudentDTO> wrapper = JoinWrapper.create(StudentDO.class, StudentDTO.class)
    .select(StudentDO::getName, StudentDTO::getStudentName)
    .select(StudentDO::getId, StudentDTO::getStudentId)
    .selectAll();
List<StudentDTO> studentDTOS = studentMapper.selectListJoin(wrapper);

该条件构造器构造的 SQL 等同:

SELECT t1.*, t1.name AS student_name, t1.id AS student_id FROM student t1

2、扩展条件

JoinWrapper基于 mp 的条件构造器原有方法额外提供三个方向的扩展:

  • 基于 Lambda 表达式的应用条件;
  • 预设的应用条件:包括 in/notInIfNotEmptyeqIfNotNulllikeIfNotBankbetween/notBetweenIfAllNotNull等;
  • 补充方法:包括 notLikeRightnotLikeLeftlimit等;

如:

JoinWrapper<StudentDO, StudentDTO> wrapper = JoinWrapper.create(StudentDO.class, StudentDTO.class)
    // 基于lambda表达式的应用条件
    .eq(Objects::nonNull, StudentDO::getName, null)
    .in(t -> !t.isEmpty(), StudentDO::getId, Arrays.asList(1, 2, 3))
    // 预设应用条件
    .eqIfNotNull(StudentDO::getName, null)
    .inIfNotEmpty(StuedntDO::getId, Collections.emptyList())
    // 补充方法
    .notLikeRight(CharSequenceUtil::isNotBlank, StudentDO::getName, "小明")
    .limit(true, 1);

List<StudentDTO> studentDTOS = studentMapper.selectListJoin(wrapper);

最终构造的 SQL同:

SELECT t1.* FROM student t1 WHERE (t1.name NOT LIKE '小明%' and t1.id in (1, 2, 3)) LIMIT 1

3、连表查询

JoinWrapper支持构造关联查询:

// 查询学生成绩
JoinWrapper<StudentDO, StudentDTO> wrapper = JoinWrapper.create(StudentDO.class, StudentDTO.class)
    .selectAll()
    .leftJoin(ScoreDO.class, w -> w
		.on(StudentDO::getId, Condition.EQ, ScoreDO::getStudentId)
		.select(ScoreDO::getScore, StudentDTO::getScore)
		.leftJoin(CourseDO.class)
		.on(ScoreDO::getCourseId, Condition.EQ, CourseDO::getId)
		.select(CourseDO::getName, StudentDTO::getCourseName)
     );

// 该写法等同于
JoinWrapper<StudentDO, StudentDTO> wrapper = JoinWrapper.create(StudentDO.class, StudentDTO.class)
	.selectAll()
	.leftJoin(ScoreDO.class, w -> w
		.on(StudentDO::getId, Condition.EQ, ScoreDO::getStudentId)
		.select(ScoreDO::getScore, StudentDTO::getScore)
		.leftJoin(CourseDO.class, w2 -> w2
			.on(ScoreDO::getCourseId, Condition.EQ, CourseDO::getId)
			.select(CourseDO::getName, StudentDTO::getCourseName)
		)
	);

该条件构造器构造的 SQL 等同:

SELECT t1.*, t2.score AS score, t3.name AS course_name 
FROM student t1 
LEFT JOIN score t2 ON (t1.id = t2.student_id) 
LEFT JOIN course t3 ON (t2.course_id = t3.id)

支持的关联查询包括 fulljoinleft joinright joininner join 四种,关联的每张表都可以添加复数的普通条件、关联条件(on)以及查询字段,比如:

JoinWrapper<StudentDO, StudentDTO> wrapper = JoinWrapper.create(StudentDO.class, StudentDTO.class)
    .selectAll()
    .eqIfNotNull(StudentDO::getName, "小明")
    .leftJoin(ScoreDO.class, w -> w
		.on(StudentDO::getId, Condition.EQ, ScoreDO::getStudentId)
		.select(ScoreDO::getScore, StudentDTO::getScore)
		.le(ScoreDO::getScore, 60)
		.leftJoin(CourseDO.class, w2 -> w2
			.on(ScoreDO::getCourseId, Condition.EQ, CourseDO::getId)
			.select(CourseDO::getName, StudentDTO::getCourseName)
			.likeIfNotBank(CourseDO::getType, "文科")
		)
	);

该条件构造器构造的 SQL 如下:

 SELECT t1.*, t2.score AS score, t3.name AS course_name
 FROM student t1
 LEFT JOIN score t2
 ON (t1.id = t2.student_id)
 LEFT JOIN course t3
 ON (t2.course_id = t3.id)
 WHERE (t1.name = '小明' AND t2.score <= 60 AND t3.type LIKE '%文科%');

4、数据库函数字段

JoinWrapper支持将数据库函数作为字段,可以有三种用法:

  • 作为查询字段,如:select ifNull(a.name, 'fack name')
  • 作为查询条件,包括 where 与 having 条件;
  • 用于函数嵌套,如 concat('user: ', ifNull(a.name, 'fack name'))

由于在关联查询时必须指定表字段来源表的别名,因此创建表字段需要通过 JoinWrapper.toTableColumn()将字段与表进行绑定,然后可通过函数字段工厂类top.xiajibagao.mybatis.plus.join.wrapper.column.Columns对获取的字段进行函数化。

支持的函数:

  • 日期类:now, currentTimestamp, currentDate, currentTime, dateFormat, day, month, year;
  • 数学:abs, avg, max, min, sum, rand, count;
  • 字符串:ifNull, concat, format, replace, upper, lower;
  • 控制流:case..then...when...else;

注意:部分函数可能不受某些数据库支持,请根据自己项目使用的数据库选择性使用

Select

如:

// 查询分数,并根据分段给出评价
JoinWrapper<ScoreDO, StudentDTO> wrapper = JoinWrapper.create(ScoreDO.class, StudentDTO.class);
wrapper.select(ScoreDO::getScore) // 查询 score 字段
    .select(ScoreDO::getCourseId, StudentDTO::getCourseId) // 查询 courseId 字段, 并指定别名为 courseId
    .selectAll() // 查询 ScoreDO 的全部字段, 效果同 select *
    .selectAllColumns() // 查询 ScoreDO 的全部字段, 效果同 select 对象中全部被 @TableField 注解的可查询字段
    .selectAllColumns(ScoreDO::getName) // 查询 ScoreDO 的全部字段, 但是并排除 name 字段
    .caseByCondition(StudentDTO::getRemark)
        .when(wrapper.toTableColumn(ScoreDO::getScore), Condition.GE, 90, "'优'")
        .when(wrapper.toTableColumn(ScoreDO::getScore), Condition.GE, 60, "'及格'")
        .el(() -> "'不及格'")
    .end();

该条件构造器构造的 SQL 同:

SELECT t1.score, (
    CASE t1.score 
    WHEN t1.score >= 90 THEN '优' 
    WHEN t1.score >= 60 THEN '及格' 
    ELSE '不及格' END
) AS remark 
FROM score t1

Where

像函数这类特殊的字段需要依靠where()方法构建:

JoinWrapper<ScoreDO, StudentDTO> wrapper = JoinWrapper.create(ScoreDO.class, StudentDTO.class);
wrapper.selectAll()
    .where(Columns.plus(wrapper.toTableColumn(ScoreDO::getScore), 5), Condition.EQ, 100);

构建的 SQL 同:

SELECT t1.* FROM score t1 WHERE ((t1.score + 5) = 100)

Having

Having 关键字需要配合 group by 使用:

// 查询挂了不止1人的科目的挂科人数
JoinWrapper<ScoreDO, StudentDTO> wrapper = JoinWrapper.create(ScoreDO.class, StudentDTO.class);
wrapper.select(ScoreDO::getCourseId, StudentDTO::getCourseId)
    .select(Columns.count(), StudentDTO::getNum)
    .where(ScoreDO::getScore, Condition.LT, 60)
    .groupBy(ScoreDO::getCourseId)
    .having(Columns.count(), Condition.GT, 1);

构建的 SQL 同:

SELECT t1.course_id AS course_id, COUNT(*) AS num 
FROM score t1 
WHERE (t1.score < 60) 
GROUP BY t1.course_id 
HAVING COUNT(*) > 1

5、子查询

JoinWrapper 允许将一个已经构造好的条件构造器转为一张逻辑表/临时表,并用于子查询。

JOIN

// 查询挂科超过1人的科目的挂科人数
JoinWrapper<ScoreDO, StudentDTO> logicTable = JoinWrapper.create(ScoreDO.class, StudentDTO.class);
logicTable.select(ScoreDO::getCourseId, StudentDTO::getCourseId)
    .select(Columns.count(), StudentDTO::getNum)
    .where(ScoreDO::getScore, Condition.LT, 60)
    .groupBy(ScoreDO::getCourseId)
    .having(Columns.count(), Condition.GT, "1");

// 查询挂科超过1人的科目的科目信息与挂科人数
JoinWrapper<CourseDO, StudentDTO> wrapper = JoinWrapper.create(CourseDO.class, StudentDTO.class);
wrapper.selectAll()
    // 关联逻辑表
    .innerJoin(logicTable)
    .on(CourseDO::getId, Condition.EQ, StudentDTO::getCourseId)
    .selectAll();

该条件构造器构造的 SQL 同:

 SELECT t1.*, t2.*
 FROM course t1
 INNER JOIN (
     SELECT t1.course_id AS course_id, COUNT(*) AS num
     FROM score t1
     WHERE (t1.score < 60) GROUP BY t1.course_id HAVING COUNT(*) > 1
 ) t2 ON (t1.id = t2.course_id);

FROM

// 查询挂科超过1人的科目及挂科人数
JoinWrapper<ScoreDO, StudentDTO> wrapper = JoinWrapper.create(ScoreDO.class, StudentDTO.class);
wrapper.select(ScoreDO::getCourseId, StudentDTO::getCourseId)
    .select(Columns.count(), StudentDTO::getNum)
    .where(ScoreDO::getScore, Condition.LT, 60)
    .groupBy(ScoreDO::getCourseId)
    .having(Columns.count(), Condition.GT, 1);

// 将上一查询转为逻辑表,然后查询该科目名称
JoinWrapper<StudentDTO, StudentDTO> logicTable = wrapper.toLogicTable()
    .selectAll()
    .leftJoin(CourseDO.class, w -> w
		.on(StudentDTO::getCourseId, Condition.EQ, CourseDO::getId)
		.select(CourseDO::getName, StudentDTO::getCourseName)
	);

该条件构造器构造的 SQL 同:

SELECT t1.*, t2.name AS course_name 
FROM (
    SELECT t1.course_id AS course_id, COUNT(*) AS num 
    FROM score t1 
    WHERE (t1.score < 60) 
    GROUP BY t1.course_id 
    HAVING COUNT(*) > 1
) t1 
LEFT JOIN course t2 ON (t1.course_id = t2.id)

WHERE

// 查询挂科人数超过1人的科目
JoinWrapper<CourseDO, StudentDTO> wrapper = JoinWrapper.create(CourseDO.class, StudentDTO.class);
wrapper.selectAll()
    .where(wrapper.toTableColumn(CourseDO::getId), Condition.IN, Columns.subQuery(
        JoinWrapper.create(ScoreDO.class, StudentDTO.class)
            .select(ScoreDO::getCourseId, StudentDTO::getCourseId)
            .where(ScoreDO::getScore, Condition.LT, 60)
            .groupBy(ScoreDO::getCourseId)
            .having(Columns.count(), Condition.GT, "1")
    ));

该条件构造器构造的 SQL 同:

SELECT t1.*
FROM course t1
WHERE (
    t1.id IN (
        SELECT t1.course_id AS course_id
        FROM score t1
        WHERE (t1.score < 60) GROUP BY t1.course_id HAVING COUNT(*) > 1
    )
);

6、原生方法适配

兼容BaseMapper方法

JoinWrapper 兼容 mp 原生 Wrapper 中setEntity()的全部查询方法,并且也可以直接作为参数传入 BaseMapper 的方法中:

// BaseMapper.selectList(Wrapper<T> wrapper)
JoinWrapper<StudentDO, StudentDTO> wrapper = JoinWrapper.create(StudentDO.class, StudentDTO.class);
List<StudentDO> students = studentMapper.selectList(wrapper);

不过这样使用时,除 Join 条件将不生效外,其余扩展功能仍可以正常使用。

逻辑删除

当配置了逻辑删除时(具体配置参见mybaits plus逻辑删除),JoinWrapper 将在初始化时,自动逻辑删除字段作为查询条件添加到 Where 条件后,关联表亦同。

假设现在已有配置:

mybatis-plus:
 global-config:
  db-config:
   logic-delete-field: isDelete
   logic-delete-value: 1
   logic-not-delete-value: 0

当我们使用条件构造成构建一个查询时,会自动从 com.baomidou.mybatisplus.core.metadata.TableInfo获取逻辑删除相关配置,并自动添加条件 logic-delete-field = login-not-delete-value,如:

JoinWrapper<StudentDO, StudentDTO> wrapper = JoinWrapper.create(StudentDO.class, StudentDTO.class);
        List<StudentDO> students = studentMapper.selectList(wrapper);

StudentDO及对于表存在字段is_delete,且已有相关逻辑删除配置,则实际构造出的 SQL 为:

SELECT * FROM student t1 where t1.is_delete = 0

分页

参见mybtis-plus分页插件,该插件基于 SQL 分析生效,因此不受影响。

但是要注意,与当使用JoinWrapper构建关联查询时,与原写法一样,若 join 的表没有 where 条件,则生成的 countSql 会忽略 join 部分的表导致查询数据行数与实际待分页数据行数不一致。

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

基于myabtis-plus的连表查询扩展,基于自定义的条件构造器支持多级join、字段别名、数据库内置函数、对 lambda 表达式支持更友好的group查询以及预设条件参数 展开 收起
Java
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/CreateSequence/mybatis-plus-join.git
git@gitee.com:CreateSequence/mybatis-plus-join.git
CreateSequence
mybatis-plus-join
mybatis-plus-join
release

搜索帮助

53164aa7 5694891 3bd8fe86 5694891