yulichang / mybatis-plus-join Goto Github PK
View Code? Open in Web Editor NEW支持连表查询的mybatis-plus,mybatis-plus风格的连表操作提供wrapper.leftJoin(),wrapper.rightJoin()等操作
Home Page: https://mybatis-plus-join.github.io
License: Apache License 2.0
支持连表查询的mybatis-plus,mybatis-plus风格的连表操作提供wrapper.leftJoin(),wrapper.rightJoin()等操作
Home Page: https://mybatis-plus-join.github.io
License: Apache License 2.0
逻辑删除时,生成的WHERE条件如下:
FROM xxx t
LEFT JOIN xxx t1 ON (t1.id = t.xxx_id)
WHERE t.DELETED = 0
AND t1.DELETED = 0
AND (t.id = ?)
ORDER BY t.id DESC
LIMIT 1;
当左表该列值为null时,返回值丢失了;
LEFT JOIN 应该保留null值;
正确的SQL应该如下:
FROM xxx t
LEFT JOIN xxx t1 ON (t1.id = t.xxx_id)
WHERE t.DELETED = 0
#AND t1.DELETED = 0
AND (t.id = ?)
ORDER BY t.id DESC
LIMIT 1;
MPJLambdaWrapper leftjoin 多次联表同一个表的时候,会提示 Not unique table/alias: 't3',而且没有办法自定义表名
nested exception is java.sql.SQLSyntaxErrorException: Not unique table/alias: 't3'
查询语句:
wrapper.and(w -> {
for(Consumer<MPJLambdaWrapper<Example>> executor : executors) {
w.or();
executor.accept(w);
}
});
此处的 w
无法定义别名(hasAlias
为 false
),导致对主表使用的默认的 t
别名
org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name '' for bean class [] conflicts with existing, non-compatible bean definition of same name and class [***]
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:348)
debug注入过程,重复的beanName 注入了两遍
问题描述:mybatis配置了三个拦截器:多租户,分页拦截器和MPJInterceptor拦截;
在项目启动时执行的sql语句,如在ApplicationRunner或者CommandLineRunner执行的初始化方法,会提示binding异常,找不到MPJ内部变量paramType_Gr8re1Ee;
在spring-boot2.0中ApplicationRunner或者CommandLineRunner执行在ApplicationStartedEvent之后执行,在ApplicationReadyEvent之前执行,所以InterceptorConfig中监听的ApplicationReadyEvent事件来更改拦截器顺序对Runner执行的sql无效
使用 selectJoinPage() 方法进行分页查询时,查询总记录条数时,没有进行表连接。
"程序错误|doDispatch(DispatcherServlet.java:1053)|Handler dispatch failed; nested exception is java.lang.AbstractMethodError: com.github.yulichang.interceptor.MPJInterceptor.plugin(Ljava/lang/Object;)Ljava/lang/Object;"
MybatisPlusJoinAutoConfiguration 的每个方法上都使用了 @ConditionalOnClass, 如果只引入了 'mybatis-plus-join-boot-starter-1.4.5` 而没有引入 mybatis 相关的依赖的话, 会找不到 class (虽然业务开发中很少存在这种情况, 不过为了保障健壮性, 应该可以优化一下)
报错信息如下
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.customer.core.mapper.CusCustomerMapper.selectJoinList;
mybatis-plus-join用的1.0.8
mybatis-plus 版本3.4.0
这个是自定义配置
@bean
@order(-2)
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//连表插件
interceptor.addInnerInterceptor(new MPJInterceptor());
return interceptor;
}
关键是这行
interceptor.addInnerInterceptor(new MPJInterceptor());
如果不把他加进去 运行时会报classCaseError
升级mybatis-plus-join版本的话,这行代码又显示无法转换MPJInterceptor类为MybatisPlusInterceptor 。只能降版本来用,好不容易项目起来了,原有sql也没问题。结果又出现了标题的报错信息。
具体原因未知,勉强点了一个星星
报错信息显示,在MPJTableMapperHelper的
public static Class getEntity(Class clazz) {
return (Class)CACHE_REVERSE.get(clazz);
}
可能传入了一个null
下面是打包的mvn配置,放在<build> <plugins>
里面
<!-- 打包jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<!--不打包资源文件 -->
<excludes>
<exclude>*.**</exclude>
<exclude>*/*.xml</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!--MANIFEST.MF 中 Class-Path 加入前缀 -->
<classpathPrefix>lib/</classpathPrefix>
<!--jar包不包含唯一版本标识 -->
<useUniqueVersions>false</useUniqueVersions>
<!--指定入口类 -->
<mainClass>com.cawis.FbsDeviceServiceApplication</mainClass>
</manifest>
<manifestEntries>
<!--MANIFEST.MF 中 Class-Path 加入资源文件目录 -->
<Class-Path>./resources/</Class-Path>
</manifestEntries>
</archive>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>
<!--拷贝依赖 copy-dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!--拷贝资源文件 copy-resources -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<!--设置自己目录下的配置文件 -->
<resource>
<!--下方resources的文件夹名字要和自己项目的文件夹名确认一致才行 很多人就是忽略了名字不一致 -->
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
<outputDirectory>${project.build.directory}/resources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!--spring boot repackage,依赖 maven-jar-plugin 打包的jar包 重新打包成 spring boot
的jar包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--重写包含依赖,包含不存在的依赖,jar里没有pom里的依赖 -->
<includes>
<include>
<groupId>null</groupId>
<artifactId>null</artifactId>
</include>
</includes>
<layout>ZIP</layout>
<!--使用外部配置文件,jar包里没有资源文件 -->
<addResources>true</addResources>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<!--配置jar包特殊标识 配置后,保留原文件,生成新文件 *-run.jar -->
<!--配置jar包特殊标识 不配置,原文件命名为 *.jar.original,生成新文件 *.jar -->
<!--<classifier>run</classifier> -->
</configuration>
</execution>
</executions>
</plugin>
> h path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
> ### Error querying database. Cause: java.lang.NullPointerException
> ### Cause: java.lang.NullPointerException] with root cause
> java.lang.NullPointerException: null
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936) ~[na:1.8.0_362]
at com.github.yulichang.mapper.MPJTableMapperHelper.getEntity(MPJTableMapperHelper.java:30) ~[mybatis-plus-join-core-1.4.4.1.jar:na]
at com.github.yulichang.interceptor.MPJInterceptor.getMappedStatement(MPJInterceptor.java:89) ~[mybatis-plus-join-core-1.4.4.1.jar:na]
at com.github.yulichang.interceptor.MPJInterceptor.intercept(MPJInterceptor.java:69) ~[mybatis-plus-join-core-1.4.4.1.jar:na]
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:62) ~[mybatis-3.5.10.jar:3.5.10]
at com.sun.proxy.$Proxy212.query(Unknown Source) ~[na:na]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151) ~[mybatis-3.5.10.jar:3.5.10]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145) ~[mybatis-3.5.10.jar:3.5.10]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140) ~[mybatis-3.5.10.jar:3.5.10]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) ~[mybatis-spring-2.0.7.jar:2.0.7]
at com.sun.proxy.$Proxy120.selectList(Unknown Source) ~[na:na]
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224) ~[mybatis-spring-2.0.7.jar:2.0.7]
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForIPage(MybatisMapperMethod.java:121) ~[mybatis-plus-core-3.5.3.1.jar:3.5.3.1]
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:85) ~[mybatis-plus-core-3.5.3.1.jar:3.5.3.1]
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) ~[mybatis-plus-core-3.5.3.1.jar:3.5.3.1]
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) ~[mybatis-plus-core-3.5.3.1.jar:3.5.3.1]
at com.sun.proxy.$Proxy139.selectJoinPage(Unknown Source) ~[na:na]
at com.cawis.service.impl.DeviceInfoServiceImpl.pageDeviceOnlineInfoVo(DeviceInfoServiceImpl.java:569) ~[classes!/:0.0.1-SNAPSHOT]
at com.cawis.service.impl.DeviceInfoServiceImpl$$FastClassBySpringCGLIB$$1a18a5f4.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:85) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704) ~[spring-aop-5.3.23.jar:5.3.23]
at com.cawis.service.impl.DeviceInfoServiceImpl$$EnhancerBySpringCGLIB$$23675066.pageDeviceOnlineInfoVo(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
at com.cawis.controller.DeviceController.onlineInfo(DeviceController.java:736) ~[classes!/:0.0.1-SNAPSHOT]
at com.cawis.controller.DeviceController$$FastClassBySpringCGLIB$$a2554ec.invoke(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:57) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.23.jar:5.3.23]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.23.jar:5.3.23]
at com.cawis.controller.DeviceController$$EnhancerBySpringCGLIB$$75afecec.onlineInfo(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_362]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_362]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_362]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_362]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1071) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:964) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.23.jar:5.3.23]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:696) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.23.jar:5.3.23]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:779) ~[tomcat-embed-core-9.0.68.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:142) ~[spring-session-core-2.6.3.jar:2.6.3]
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:82) ~[spring-session-core-2.6.3.jar:2.6.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.23.jar:5.3.23]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.23.jar:5.3.23]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.68.jar:9.0.68]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.68.jar:9.0.68]
at java.lang.Thread.run(Thread.java:750) [na:1.8.0_362]
对于Kotlin类型的Entity,好像没法使用
val dList = deviceService.baseMapper.selectJoinList(
DeviceInfo::class.java, MPJLambdaWrapper<Device>()
.selectAll(DeviceInfo::class.java)
.leftJoin(DeviceInfo::class.java, DeviceInfo::deviceNo, Device::deviceNo)
.eq(Device::ownerId, owner.id)
)
error
该方法仅能传入 lambda 表达式产生的合成类
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: 该方法仅能传入 lambda 表达式产生的合成类
at com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:49)
at com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda.resolve(SerializedLambda.java:56)
at com.baomidou.mybatisplus.core.toolkit.LambdaUtils.lambda$resolve$0(LambdaUtils.java:64)
at java.util.Optional.orElseGet(Optional.java:267)
at com.baomidou.mybatisplus.core.toolkit.LambdaUtils.resolve(LambdaUtils.java:63)
at com.github.yulichang.toolkit.LambdaUtils.getColumn(LambdaUtils.java:29)
at com.github.yulichang.wrapper.MPJLambdaWrapper.join(MPJLambdaWrapper.java:210)
at com.github.yulichang.wrapper.MPJLambdaWrapper.join(MPJLambdaWrapper.java:29)
at com.github.yulichang.wrapper.interfaces.LambdaJoin.leftJoin(LambdaJoin.java:17)
at com.github.yulichang.wrapper.interfaces.LambdaJoin.leftJoin(LambdaJoin.java:13)
at DeviceInfoController.list(DeviceInfoController.kt:46)
1.2.4
不同的实体数据库表,都有相同的查询条件,构造MPJLambdaWrapper时,期望不需要每个实体类都去处理一遍这些查询条件,相同的查询条件定义泛型方法来处理
1,定义两个数据库实体,相同的字段放到基类Base
class Base {
Long id;
Long appId;
}
class A extends Base {
String fieldA;
}
class B extends Base {
String fieldB;
}
2,定义查询条件的泛型处理方法
protected <E extends Base> void handleAppId(MPJLambdaWrapper<E> qw, Long appId) {
if (appId != null) {
if (appId == -1L) {
qw.eq(E::getAppId, -1L);
} else {
qw.and(t -> t.eq(E::getAppId, -1L)
.or().eq(E::getAppId, appId));
}
}
}
3,查询报错
空指针异常,ColumnCache 字段缓存里面没有找到
nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'ew.sqlSegment != null and ew.sqlSegment != '' and ew.nonEmptyOfWhere'. Cause: org.apache.ibatis.ognl.OgnlException: sqlSegment [java.lang.NullPointerException]
com.github.yulichang.wrapper.MPJAbstractLambdaWrapper, getCache(), 57
com.github.yulichang.wrapper.MPJAbstractLambdaWrapper, columnToString(), 47
com.github.yulichang.wrapper.MPJAbstractLambdaWrapper, columnToString(), 36
debug 可以看到缓存字段 columnMap 中只有 ClassA和ClassB,不会有个ClassBase,但是泛型Lambda传入的是ClassBase
比如一张表里面有:createUser,updateUser两个参数都需要join User表就会报错,好像没找到解决办法?
查询出来数据records :6 total:8 size :10
比如 UserA 有个属性 Contact 用了 FieldMapping , Contact 内又有个 Email 属性用了 FieldMapping ,支持递归吗?
如果支持,那嵌套深度有限制吗(可能会出现无限递归)
这种情况有办法处理吗?
mp的3.5.3.1变化还是有点大的
我有这样的需求:
我的数据库中有character表、character_skill表
character表中主键为id
character_skill表是一个中间表,其中除了character_id和skill_id作为双主键外,还有几个字段例如grow_value,profession_value等,
代表技能的成长值和职业点值,这些字段是每个角色的每个技能独有的,所以我将这些字段直接放到了character和skill关联的中间表中,
而由于需要在character实体类传给前端的时候有一个List ownSkills字段存放每个角色拥有技能的一些独有值(不想将character_id传过去),所以我在后端增加了一个OwnSkill实体类去拿中间表的这几个grow_value、profession_value等字段
我的OwnSkill并没有character_id这个字段,他只放每个角色拥有的每个技能的独有值
这个OwnSkill实体类作为Character类的一个虚拟字段(即character数据表中不存在这个字段)
使用关联查询
由于OwnSkill这个实体类并没有在数据库中存在,无法直接进行映射,请问使用MPJLambdaWrapper的leftJoin是否有办法实现这种间接的映射,比如我想通过leftJoin将character_skill这个中间表需要用到的字段数据取出来然后赋值给Character的OwnSkills字段
就例如我使用xml实现的
请问目前使用mpj能实现这种需求吗,我看了文档似乎没看到有这种将字段给不同于表映射的实体类的地方,请多指教
1.3.6版本MPJLambdaWrapper 的 wrapper.getLogicSql() 空指针
连表查询时,多个条件构造器连续使用condition参数来控制SQL是否拼接,当condition参数传入 对布尔包装类型参数的null判断 会出现空指针异常问题,还有LocalDateTime数组 对象 null值判断 ,其他类型暂未出现
环境:
springboot 版本2.6.6:
@Component
public class InitRunner implements CommandLineRunner {
}
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join</artifactId>
<version>1.2.3</version>
</dependency>
启动时报错:
Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'paramType_Gr8re1Ee' not found. Available parameters are [ew, param1]
原生Mp的selectList不支持返回另一个DTO,这边可否增加一个这样的方法呢?当然目前使用selectJoinList也可以,只是我不join其他表而已。
DTO & DO
dtoX {
string a,
int b
List<dtoY> c
}
dtoY {
string d
}
doX {
string a,
int b
}
doY {
int b
string d
}
查询
List<dtoX> list = mapperX.selectJoinList(dtoX.class,
new MPLambdaWrapper<doX>()
.selectAll(doX.class)
.select(doY.d)
.leftJoin(doY.class,doY::b,doX::b)
);
对于这样的查询,该如何设置dtoX
的List<dtoY> c
呢?
我这条sql会报错,因为别名重复,连接了两次sys_dictionary表,但是别名都是一样的
IPage<HiddenTroubleVo> page = hiddenTroubleMapper.selectJoinPage( new Page<HiddenTroubleVo>(param.getPage(), param.getLimit()), HiddenTroubleVo.class, new MPJLambdaWrapper<HiddenTrouble>() .selectAll(HiddenTrouble.class) .selectAs(SysDictionary::getName, HiddenTroubleVo::getTypeName) .selectAs(User::getName, HiddenTroubleVo::getCreateUserName) .selectAs(SysDictionary::getName, HiddenTroubleVo::getStatusName) .leftJoin(SysDictionary.class, (on) -> on.eq(SysDictionary::getValue, HiddenTrouble::getType) .eq(SysDictionary::getType, SysDictionaryType.HIDDEN_TROUBLE_TYPE) ) .leftJoin(User.class, User::getId, HiddenTrouble::getCreateUser) .leftJoin(ServiceAgency.class, ServiceAgency::getId, HiddenTrouble::getServiceAgencyId) .leftJoin(SysDictionary.class, (on) -> on.eq(SysDictionary::getValue, HiddenTrouble::getType) .eq(SysDictionary::getType, SysDictionaryType.HIDDEN_TROUBLE_STATUS) ) );
pojo
@TableName("\"ST_STBPRP_B\"")
@EqualsAndHashCode(callSuper = true)
public class ST_STBPRP_B extends GeometryBaseEntity implements Serializable {
/**
* 测站名
*/
@TableField("\"STNM\"")
private String stnm;
}
service
var like = new MPJLambdaWrapper<ST_STBPRP_B>()
.select(ST_STBPRP_B::getStnm)
.like(ST_STBPRP_B::getStnm, stnm);
mapper.selectOne(like)
结果
### SQL: SELECT t."STNM" FROM "ST_STBPRP_B" t WHERE (t.STNM LIKE ?)
### Cause: org.postgresql.util.PSQLException: ERROR: column t.stnm does not exist
从拼接出来的sql可以看到like条件STNM并没有按照 @TableField中的value一致,但是在select中是正确的
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4f664bee] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1238145834 wrapping com.mysql.cj.jdbc.ConnectionImpl@6befbb12] will not be managed by Spring
==> Preparing: SELECT COUNT( * ) FROM certificate_revocation t LEFT JOIN crl_operation t2 on t2.revocation_id = t.id WHERE (t.id = ?)
==> Parameters: 1(Integer)
<== Columns: COUNT( * )
<== Row: 5
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4f664bee]
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
at com.sun.proxy.$Proxy93.selectJoinCount(Unknown Source)
at com.cicv.ma.common.db.mapper.RepoTest.joinTest(RepoTest.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
@Test
public void joinTest() {
MPJLambdaWrapper lambw = new MPJLambdaWrapper<>()
.leftJoin(CrlOperation.class, CrlOperation::getRevocationId, CertificateRevocation::getId)
.eq(CertificateRevocation::getId, 1);
System.out.println(revocationService.selectJoinCount(qw).longValue());
}
table not find by class
怎么解决?
多对多查询,三表left join,出现以下问题
Caused by: org.apache.ibatis.ognl.OgnlException: from [java.lang.NullPointerException: Cannot invoke "com.baomidou.mybatisplus.core.metadata.TableInfo.getTableName()" because the return value of "com.baomidou.mybatisplus.core.metadata.TableInfoHelper.getTableInfo(java.lang.Class)" is null]
Caused by: java.lang.NullPointerException: Cannot invoke "com.baomidou.mybatisplus.core.metadata.TableInfo.getTableName()" because the return value of "com.baomidou.mybatisplus.core.metadata.TableInfoHelper.getTableInfo(java.lang.Class)" is null
已经在entity上加了@TableName
表如下
@Data
@TableName("table_a")
public class TableA {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
}
@Data
@TableName("table_b")
public class TableB {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
}
@Data
@TableName("table_a_b")
public class TableAB{
private Long aId;
private Long bId;
}
查询
var page = new Page<TableA>(1, 2);
var pages = TableAMapper.selectJoinPage(page, TableA.class, new MPJLambdaWrapper<TableA>()
.selectAll(TableA.class)
.leftJoin(TableAB.class, TableAB::getAId, TableA::getId)
.leftJoin(TableB.class, TableB::getId, TableAB::getBId));
jdk:
openjdk 17.0.4.1 2022-08-12 LTS
OpenJDK Runtime Environment Corretto-17.0.4.9.1 (build 17.0.4.1+9-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.4.9.1 (build 17.0.4.1+9-LTS, mixed mode, sharing)
mybatis plus 、mybatis plus join 、spring boot 版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join</artifactId>
<version>1.2.4</version>
</dependency>
SELECT A.id
FROM A left join B
on A.id=B.a_id and A.xx=12 and B.id<100
如何实现这样的查询?
我需要查询记录数和数据
select * from user t inner user t2 on t.id = t1.id
正常写会解析成t.id = t.id, 使用lambajoin能否强制设置第一个参数为前一张表,第二个参数为后一张表
Hello,
When running the package I get the following error:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): {packagename}.{entity}Dao.selectJoinPage
at org.apache.ibatis.binding.MapperMethod$SqlCommand.(MapperMethod.java:235)
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.(MybatisMapperMethod.java:51)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.lambda$cachedInvoker$0(MybatisMapperProxy.java:111)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at com.baomidou.mybatisplus.core.toolkit.CollectionUtils.computeIfAbsent(CollectionUtils.java:117)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.cachedInvoker(MybatisMapperProxy.java:98)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
at com.sun.proxy.$Proxy158.selectJoinPage(Unknown Source)
I am running MybatisPlus 3.4.2 with mybatis-plus-join-boot-starter 1.3.11
Online I only find answers that advise me to move my mapper.xml but just like in the example, I don't use an xml.
Thank you in advance!
只使用了selectAll和selectAssociation以及在selectAssociation中多次使用association,且分页时传入的一页展示10条,但结果返回的数据只有两条,结果超出实际数据条数。实际通过生成出的sql执行发现只有10条数据
MPJLambdaWrapper<CoursescheduleTimesDO> lqw = new MPJLambdaWrapper<CoursescheduleTimesDO>()
.selectAll(CoursescheduleTimesDO.class)
.selectAssociation(CoursescheduleBasicinfoDO.class, CoursescheduleTimesRespVO::getBasicinfoIdObj,map->map
.result(CoursescheduleBasicinfoDO::getCreateTime)
.result(CoursescheduleBasicinfoDO::getCourseinfoId)
.result(CoursescheduleBasicinfoDO::getTerminfoId)
.result(CoursescheduleBasicinfoDO::getTchinfoId)
.result(CoursescheduleBasicinfoDO::getClassinfoId)
.result(CoursescheduleBasicinfoDO::getIsOptional)
.result(CoursescheduleBasicinfoDO::getIsPublic)
.association(ClasssysClassinfoDO.class, CoursescheduleBasicinfoRespVO::getClassinfoIdObj)
.association(CoursesysCourseinfoDO.class, CoursescheduleBasicinfoRespVO::getCourseinfoIdObj)
.association(TermsysTerminfoDO.class,CoursescheduleBasicinfoRespVO::getTerminfoIdObj)
.association(TchinfoInfoDO.class,CoursescheduleBasicinfoRespVO::getTchinfoIdObj)
)
.selectAssociation(CourseadjustAdjustinfoDO.class, CoursescheduleTimesRespVO::getAdjustinfoIdObj,map->map
.result(CourseadjustAdjustinfoDO::getCreateTime)
.result(CourseadjustAdjustinfoDO::getTimesId)
.result(CourseadjustAdjustinfoDO::getProcessInstanceId)
.result(CourseadjustAdjustinfoDO::getResult)
.result(CourseadjustAdjustinfoDO::getNewWeekNum)
.result(CourseadjustAdjustinfoDO::getNewStartTimes)
.result(CourseadjustAdjustinfoDO::getNewEndTimes)
.result(CourseadjustAdjustinfoDO::getNewWeek)
)
.between(reqVO.getCreateTime() != null, CoursescheduleTimesDO::getCreateTime,
ArrayUtil.get(reqVO.getCreateTime(), 0),
ArrayUtil.get(reqVO.getCreateTime(), 1)
)
.in(!classinfoIds.isEmpty(),ClasssysClassinfoDO::getId,classinfoIds)
.eq(reqVO.getWeekNum() != null,CoursescheduleTimesDO::getWeekNum, reqVO.getWeekNum())
.eq(reqVO.getStartTimes() != null,CoursescheduleTimesDO::getStartTimes, reqVO.getStartTimes())
.eq(reqVO.getEndTimes() != null,CoursescheduleTimesDO::getEndTimes, reqVO.getEndTimes())
.eq(reqVO.getWeek() != null,CoursescheduleTimesDO::getWeek, reqVO.getWeek())
.eq(reqVO.getBasicinfoId() != null,CoursescheduleTimesDO::getBasicinfoId, reqVO.getBasicinfoId())
.eq(reqVO.getAdjustinfoId() != null,CoursescheduleTimesDO::getAdjustinfoId, reqVO.getAdjustinfoId())
.leftJoin(
CoursescheduleBasicinfoDO.class,
CoursescheduleBasicinfoDO::getId,
CoursescheduleTimesDO::getBasicinfoId
)
.leftJoin(
ClasssysClassinfoDO.class,
ClasssysClassinfoDO::getId,
CoursescheduleBasicinfoDO::getClassinfoId
)
.leftJoin(
CourseadjustAdjustinfoDO.class,
CourseadjustAdjustinfoDO::getId,
CoursescheduleTimesDO::getAdjustinfoId
)
.leftJoin(
CoursesysCourseinfoDO.class,
CoursesysCourseinfoDO::getId,
CoursescheduleBasicinfoDO::getCourseinfoId
)
.leftJoin(
StuinfoBasicDO.class,
StuinfoBasicDO::getClassinfoId,
ClasssysClassinfoDO::getId
)
.leftJoin(
TermsysTerminfoDO.class,
TermsysTerminfoDO::getId,
CoursescheduleBasicinfoDO::getTerminfoId
)
.leftJoin(
TchinfoInfoDO.class,
TchinfoInfoDO::getId,
CoursescheduleBasicinfoDO::getTchinfoId
)
.orderByDesc(CoursescheduleTimesDO::getId);
Page<CoursescheduleTimesRespVO> res = coursescheduleTimesMapper.selectJoinPage(MyBatisUtils.buildPage(reqVO), CoursescheduleTimesRespVO.class, lqw);
原来一分钟 现在差不多要三分钟 是我使用不对么 都是按文档来使用的
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xxx.mapper.IMailTemplateMapper.selectJoinList
启动时,我检查相关join包中的类都已经注入了
com.github.yulichang.config.InterceptorConfig中在sqlSessionFactoryList已经看到了mpjInterceptor
这样使用kotlin,发现会报错
override fun findByJoinLimit(): List? {
val wrapper: MPJLambdaWrapper = MPJLambdaWrapper()
.selectAll(ProductDataEntity::class.java)
// .selectAll(ProductInfoEntity::class.java)
.leftJoin(ProductInfoEntity::class.java, ProductInfoEntity::sku, ProductDataEntity::sku)
return productDataJoinMapper.selectJoinList(ProductDataJoinEntity::class.java, wrapper)
}
Caused by: org.apache.ibatis.reflection.ReflectionException: Error parsing property name 'findByJoinLimit$lambda$0'. Didn't start with 'is', 'get' or 'set'.
能显示跨库查询吗
执行查询条件为Boolean类型时,实际生成sql示例:字段 = ‘true’,期望 字段 = 0
2023-04-27 17:03:46.550 WARN 54268 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mpjSpringContent' defined in class path resource [com/github/yulichang/autoconfigure/MybatisPlusJoinAutoConfiguration.class]: Unsatisfied dependency expressed through method 'mpjSpringContent' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration$MPJSpringContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
2023-04-27 17:03:46.606 INFO 54268 --- [ main] c.b.d.d.DynamicRoutingDataSource : dynamic-datasource start closing ....
2023-04-27 17:03:46.616 INFO 54268 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closing ...
2023-04-27 17:03:46.618 INFO 54268 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} closed
2023-04-27 17:03:46.619 INFO 54268 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-2} closing ...
2023-04-27 17:03:46.620 INFO 54268 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-2} closed
2023-04-27 17:03:46.622 INFO 54268 --- [ main] c.b.d.d.DynamicRoutingDataSource : dynamic-datasource all closed success,bye
2023-04-27 17:03:46.886 INFO 54268 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-04-27 17:03:47.386 ERROR 54268 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
APPLICATION FAILED TO START
Description:
Parameter 0 of method mpjSpringContent in com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration required a bean of type 'com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration$MPJSpringContext' that could not be found.
Action:
Consider defining a bean of type 'com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration$MPJSpringContext' in your configuration.
这个需要在配置类中额外配置什么吗?
因为 MybatisPlusJoinAutoConfiguration.mpjSqlInjector 和 MybatisPlusJoinAutoConfiguration.mpjSqlInjectorOnMiss 会创建 ISqlInjector 的实例, 然而如果业务代码也需要创建 ISqlInjector 的时间, 就会导致存在多个 bean:
Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.baomidou.mybatisplus.core.injector.ISqlInjector' available: expected single matching bean but found 2: mpjSqlInjectorOnMiss,sqlInjector
有如下三张表且关系如下:
Teacher <----一对多----> User<----多对一----->Class
现在想要知道某个teacherId老师下所有学生的信息以及各个学生的班级名称,我使用如下wrapper
MPJLambdaWrapper wrapper = new MPJLambdaWrapper()
.selectAll(Teacher.class)
.select(Class::getClassName)
.selectCollection(User.class,ResDTO::getUserList)
.leftJoin(User.class, User::getUserId, Teacher::getUserId)
.leftJoin(Class.class,Class::getClassId,SealAuditTask::getClassId)
.eq(Teacher::getTeacherId,teacherId);
teacherMapper.selectJoinOne(ResDTO.class,wrapper);
这样子的话,通过日志看到SQL语句确实能够正确执行,且班级名称ClassName也返回了,但是由于不知道如何定义ResDTO所以返回的ResDTO对象中并没有这个属性,怎么加都没法注入,希望看看。
目前的ResDTO如下:
@DaTa
public class ResDTO {
private Integer teacherId;
private List users;
}
platform和merchant是一对多关系。
做关联count+group的时候,需要格式化结果, groupBy函数不够自然或者存在bug
MPJLambdaWrapper<Merchant> qw = new MPJLambdaWrapper<>();
qw.selectCount(Merchant::getId, CandidateValue::getValue);
qw.selectAs(Platform::getName, CandidateValue::getTitle);
// qw.groupBy(CandidateValue::getTitle); // 报错 mapper not find by class <CandidateValue>
// qw.groupBy(Platform::getName); // 报错, sql 是GROUP BY t.name,应该是title
qw.groupBy("title"); // ok,但是不如上面的两种方式自然
qw.leftJoin(Platform.class, Platform::getId, Merchant::getPlatform);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.