Code Monkey home page Code Monkey logo

mybatis-flex's Introduction

English | 简体中文

MyBatis-Flex is an elegant Mybatis Enhancement Framework.

Maven Apache 2 jdk-8 jdk-11 jdk-17

Gitee star Github star

Features

  1. MyBatis-Flex is very lightweight, and it only depends on Mybatis and no other third-party dependencies
  2. Basic CRUD operator and paging query of Entity class
  3. Row mapping support, you can add, delete, modify and query the database without entity classes
  4. Support multiple databases, and expand through dialects flexibly
  5. Support combined primary keys and different primary key content generation strategies
  6. Extremely friendly SQL query, IDE automatically prompts and no worries about mistakes
  7. More little surprises

hello world(Without Spring)

step 1: write entity class

@Table("tb_account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;
    private String userName;
    private Date birthday;
    private int sex;

    // getter setter
}

step 2: write mapper class(it needs extends BaseMapper)

public interface AccountMapper extends BaseMapper<Account> {
    // only Mapper interface define
}

step 3: start query data

e.g. 1: query by primary key

class HelloWorld {
    public static void main(String... args) {

        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/mybatis-flex");
        dataSource.setUsername("username");
        dataSource.setPassword("password");

        MybatisFlexBootstrap.getInstance()
                .setDataSource(dataSource)
                .addMapper(AccountMapper.class)
                .start();

        AccountMapper mapper = MybatisFlexBootstrap.getInstance()
                .getMapper(AccountMapper.class);


        // id = 100
        Account account = mapper.selectOneById(100);
    }
}

e.g.2: query list

// use QueryWrapper to build query conditions
QueryWrapper query = QueryWrapper.create()
        .select()
        .from(ACCOUNT)
        .where(ACCOUNT.ID.ge(100))
        .and(ACCOUNT.USER_NAME.like("zhang").or(ACCOUNT.USER_NAME.like("li")));

// execute SQL:
// SELECT * FROM tb_account
// WHERE tb_account.id >=  100
// AND (tb_account.user_name LIKE '%zhang%' OR tb_account.user_name LIKE '%li%' )
List<Account> accounts = mapper.selectListByQuery(query);

e.g.3: paging query

// use QueryWrapper to build query conditions
QueryWrapper query = QueryWrapper.create()
        .select()
        .from(ACCOUNT)
        .where(ACCOUNT.ID.ge(100))
        .and(ACCOUNT.USER_NAME.like("zhang").or(ACCOUNT.USER_NAME.like("li")))
        .orderBy(ACCOUNT.ID.desc());

// execute SQL:
// SELECT * FROM tb_account
// WHERE tb_account.id >=  100
// AND (tb_account.user_name LIKE '%zhang%' OR tb_account.user_name LIKE '%li%' )
// ORDER BY tb_account.id DESC
// LIMIT 40,10
Page<Account> accountPage = mapper.paginate(5, 10, query);

QueryWrapper Samples

select *

QueryWrapper query = new QueryWrapper();
query.select().from(ACCOUNT)

// SQL:
// SELECT * FROM tb_account

select columns

QueryWrapper query = new QueryWrapper();
query.select(ACCOUNT.ID,ACCOUNT.USER_NAME).from(ACCOUNT)

// SQL:
// SELECT tb_account.id, tb_account.user_name
// FROM tb_account
QueryWrapper query = new QueryWrapper()
    .select(ACCOUNT.ID
        , ACCOUNT.USER_NAME
        , ARTICLE.ID.as("articleId")
        , ARTICLE.TITLE)
    .from(ACCOUNT.as("a"), ARTICLE.as("b"))
    .where(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID));

// SQL:
// SELECT a.id, a.user_name, b.id AS articleId, b.title
// FROM tb_account AS a, tb_article AS b
// WHERE a.id = b.account_id

select functions

 QueryWrapper query = new QueryWrapper()
        .select(
            ACCOUNT.ID,
            ACCOUNT.USER_NAME,
            max(ACCOUNT.BIRTHDAY),
            avg(ACCOUNT.SEX).as("sex_avg")
        ).from(ACCOUNT);

// SQL:
// SELECT tb_account.id, tb_account.user_name,
// MAX(tb_account.birthday),
// AVG(tb_account.sex) AS sex_avg
// FROM tb_account

where

QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(ACCOUNT.USER_NAME.like("michael"));

// SQL:
// SELECT * FROM tb_account
// WHERE tb_account.id >=  ?
// AND tb_account.user_name LIKE  ?

exists, not exists

QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(
        exists(
            selectOne().from(ARTICLE).where(ARTICLE.ID.ge(100))
        )
    );

// SQL:
// SELECT * FROM tb_account
// WHERE tb_account.id >=  ?
// AND EXIST (
//  SELECT 1 FROM tb_article WHERE tb_article.id >=  ?
// )

and (...) or (...)

QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .where(ACCOUNT.ID.ge(100))
    .and(ACCOUNT.SEX.eq(1).or(ACCOUNT.SEX.eq(2)))
    .or(ACCOUNT.AGE.in(18,19,20).or(ACCOUNT.USER_NAME.like("michael")));

// SQL:
// SELECT * FROM tb_account
// WHERE tb_account.id >=  ?
// AND (tb_account.sex =  ?  OR tb_account.sex =  ? )
// OR (tb_account.age IN (?,?,?) OR tb_account.user_name LIKE  ? )

group by

QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .groupBy(ACCOUNT.USER_NAME);

// SQL:
// SELECT * FROM tb_account
// GROUP BY tb_account.user_name

having

QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .groupBy(ACCOUNT.USER_NAME)
    .having(ACCOUNT.AGE.between(18,25));

// SQL:
// SELECT * FROM tb_account
// GROUP BY tb_account.user_name
// HAVING tb_account.age BETWEEN  ? AND ?

orderBy

QueryWrapper queryWrapper = QueryWrapper.create()
        .select()
        .from(ACCOUNT)
        .orderBy(ACCOUNT.AGE.asc(), ACCOUNT.USER_NAME.desc().nullsLast());

// SQL:
// SELECT * FROM tb_account
// ORDER BY age ASC, user_name DESC NULLS LAST

join

QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
    .where(ACCOUNT.AGE.ge(10));

// SQL:
// SELECT * FROM tb_account
// LEFT JOIN tb_article
// ON tb_account.id = tb_article.account_id
// WHERE tb_account.age >=  ?

limit... offset

QueryWrapper queryWrapper = QueryWrapper.create()
    .select()
    .from(ACCOUNT)
    .orderBy(ACCOUNT.ID.desc())
    .limit(10)
    .offset(20);

// MySql:
// SELECT * FROM `tb_account` ORDER BY `id` DESC LIMIT 20, 10

// PostgreSQL:
// SELECT * FROM "tb_account" ORDER BY "id" DESC LIMIT 20 OFFSET 10

// Informix:
// SELECT SKIP 20 FIRST 10 * FROM "tb_account" ORDER BY "id" DESC

// Oracle:
// SELECT * FROM (SELECT TEMP_DATAS.*,
//  ROWNUM RN FROM (
//          SELECT * FROM "tb_account" ORDER BY "id" DESC)
//      TEMP_DATAS WHERE  ROWNUM <=30)
//  WHERE RN >20

// Db2:
// SELECT * FROM "tb_account" ORDER BY "id" DESC
// OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY

// Sybase:
// SELECT TOP 10 START AT 21 * FROM "tb_account" ORDER BY "id" DESC

// Firebird:
// SELECT * FROM "tb_account" ORDER BY "id" DESC ROWS 20 TO 30

Questions?

1. How to generate "ACCOUNT" class for QueryWrapper by Account.java ?

Build the project by IDE, or execute maven build command: mvn clean package

More Samples

  1. Mybatis-Flex Only (Native)
  2. Mybatis-Flex with Spring
  3. Mybatis-Flex with Spring boot

Wechat Group

mybatis-flex's People

Contributors

925966998 avatar cloudplayer114514 avatar dcrpp avatar farukonfly avatar font-c avatar frozenfield avatar ice-small avatar imtzc avatar jiandanfeng avatar kamo030 avatar kiratan avatar lhzsdnu avatar lifejwang11 avatar minliuhua avatar mofan212 avatar noear avatar piggsoft avatar rainybx avatar ruansheng8 avatar snyk-bot avatar suomm avatar swqxdba avatar tangxin-li avatar timnick-snow avatar witt-bit avatar wujlinlin avatar xuan25575 avatar yangfuhai avatar ymind avatar z2z2qp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mybatis-flex's Issues

分页查询生成的查询总数语句问题

查询:

@GetMapping("/page")
    Page<TenantDTO> page(@RequestParam int page, @RequestParam int size) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(TENANT.ID)
                .from(TENANT);
        Page<TenantDTO> tenantDTOPage = tenantMapper.paginateAs(Page.of(page, size), queryWrapper, TenantDTO.class, fieldQueryBuilder -> fieldQueryBuilder
                .field(TenantDTO::getUsers)
                .queryWrapper(tenant -> QueryWrapper.create()
                        .select().from(USER)
                        .where(USER.TENANT_ID.eq(TENANT.ID))
                )
        );
        return tenantDTOPage;
    }

报错:为什么不是是COUNT(*)或者COUNT(id)

### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: (conn=204) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') AS `total` FROM `tenant`' at line 1
### The error may exist in com/mybatisflex/admin/mapper/TenantMapper.java (best guess)
### The error may involve com.mybatisflex.admin.mapper.TenantMapper.selectObjectListByQuery-Inline
### The error occurred while setting parameters
### SQL: SELECT COUNT() AS `total` FROM `tenant`
### Cause: java.sql.SQLSyntaxErrorException: (conn=204) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') AS `total` FROM `tenant`' at line 1
; bad SQL grammar []] with root cause

java.sql.SQLSyntaxErrorException: (conn=204) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ') AS `total` FROM `tenant`' at line 1
	at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:282) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.export.ExceptionFactory.create(ExceptionFactory.java:370) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.message.ClientMessage.readPacket(ClientMessage.java:134) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.client.impl.StandardClient.readPacket(StandardClient.java:872) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.client.impl.StandardClient.readResults(StandardClient.java:811) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.client.impl.StandardClient.readResponse(StandardClient.java:730) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.client.impl.StandardClient.execute(StandardClient.java:654) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:95) ~[mariadb-java-client-3.1.4.jar:na]
	at org.mariadb.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:268) ~[mariadb-java-client-3.1.4.jar:na]
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44) ~[HikariCP-5.0.1.jar:na]
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java) ~[HikariCP-5.0.1.jar:na]
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65) ~[mybatis-3.5.13.jar:3.5.13]
	at com.mybatisflex.core.mybatis.FlexStatementHandler.lambda$query$2(FlexStatementHandler.java:100) ~[classes/:na]
	at com.mybatisflex.core.audit.AuditManager.startAudit(AuditManager.java:104) ~[classes/:na]
	at com.mybatisflex.core.mybatis.FlexStatementHandler.query(FlexStatementHandler.java:100) ~[classes/:na]
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:65) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:333) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:158) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:110) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:90) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:154) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:142) ~[mybatis-3.5.13.jar:3.5.13]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:425) ~[mybatis-spring-3.0.1.jar:3.0.1]
	at jdk.proxy2/jdk.proxy2.$Proxy67.selectList(Unknown Source) ~[na:na]
	at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224) ~[mybatis-spring-3.0.1.jar:3.0.1]
	at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:142) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) ~[mybatis-3.5.13.jar:3.5.13]
	at jdk.proxy3/jdk.proxy3.$Proxy71.selectObjectListByQuery(Unknown Source) ~[na:na]
	at com.mybatisflex.core.BaseMapper.selectCountByQuery(BaseMapper.java:656) ~[classes/:na]
	at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732) ~[na:na]
	at org.apache.ibatis.binding.MapperProxy$DefaultMethodInvoker.invoke(MapperProxy.java:155) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) ~[mybatis-3.5.13.jar:3.5.13]
	at jdk.proxy3/jdk.proxy3.$Proxy71.selectCountByQuery(Unknown Source) ~[na:na]
	at com.mybatisflex.core.BaseMapper.paginateAs(BaseMapper.java:776) ~[classes/:na]
	at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732) ~[na:na]
	at org.apache.ibatis.binding.MapperProxy$DefaultMethodInvoker.invoke(MapperProxy.java:155) ~[mybatis-3.5.13.jar:3.5.13]
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) ~[mybatis-3.5.13.jar:3.5.13]
	at jdk.proxy3/jdk.proxy3.$Proxy71.paginateAs(Unknown Source) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at com.mybatisflex.core.mybatis.MapperInvocationHandler.invoke(MapperInvocationHandler.java:75) ~[classes/:na]
	at jdk.proxy3/jdk.proxy3.$Proxy71.paginateAs(Unknown Source) ~[na:na]
	at com.mybatisflex.admin.controller.TenantController.page(TenantController.java:55) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207) ~[spring-web-6.0.10.jar:6.0.10]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152) ~[spring-web-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.10.jar:6.0]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.0.10.jar:6.0.10]
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.10.jar:6.0]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.0.10.jar:6.0.10]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.10.jar:6.0.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.0.10.jar:6.0.10]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.10.jar:6.0.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.0.10.jar:6.0.10]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.0.10.jar:6.0.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-10.1.10.jar:10.1.10]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

疑惑

YE((45K4{IP$PJ JALIQ374

这里为什么要new ArrayList
而不是修改Mapper中的List为Collection

代码生成器问题

如果我不需要生成Service接口注释掉如图,
S6%IIHGB4_RH0JG 561O~PI

会导致后续ServiceImpl以及Controller 找不到 Service类;
在极端点,作为测试去测试,如果我没开启Entity的生成,那全部都飘红了

QueryWrapper 不能使用超过一次

你好,

在第一次使用queryWrapper 之后, 第二次返回的数据会异常

例子:
QueryWrapper query = QueryWrapper.create()
.where(paymentTerm.ptMerchant.eq(userBean.getMerchant()))
.and(paymentTerm.ptDesc.like(FilterUtil.search(subFilter.getDescription())))
.and(paymentTerm.ptStatus.eq(FilterUtil.search(subFilter.getStatus())))
.and(paymentTerm.ptStatus.ne(PaymentTermBean.STATUS_REMOVED))
.orderBy(filter.getSort().sortBy());

return count(query) == 0 ? new ArrayList<>() : list(query);

在以上的例子中 count(query) 返回的数量是对的, 但是 list(query) 里返回 list size = 1 但是里面是 null

无法使用UpdateEntity

想要执行的代码:

AccountDAO updateAccount = UpdateEntity.of(AccountDAO.class, info.getId());
updateAccount.setAge(info.getAge());

mapper.update(updateAccount); // 执行 <Mapper> 里的 <update()>
// updateById(updateAccount); // 执行 <ServiceImpl> 里的 <updateById()>

以下是报错的信息:

Caused by: org.apache.ibatis.builder.BuilderException: Error invoking SqlProvider method 'public static java.lang.String com.mybatisflex.core.provider.EntitySqlProvider.update(java.util.Map,org.apache.ibatis.builder.annotation.ProviderContext)' with specify parameter 'class org.apache.ibatis.binding.MapperMethod$ParamMap'.  Cause: java.lang.NullPointerException: Cannot invoke "com.mybatisflex.core.table.ColumnInfo.buildTypeHandler()" because "columnInfo" is null
  at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:209)
  at org.apache.ibatis.builder.annotation.ProviderSqlSource.getBoundSql(ProviderSqlSource.java:165)
  at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:320)
  at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:65)
  at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:42)
  at com.mybatisflex.core.mybatis.FlexPreparedStatementHandler.<init>(FlexPreparedStatementHandler.java:38)
  at com.mybatisflex.core.mybatis.FlexStatementHandler.<init>(FlexStatementHandler.java:58)
  at com.mybatisflex.core.mybatis.FlexConfiguration.newStatementHandler(FlexConfiguration.java:117)
  at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
  at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
  at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
  at jdk.proxy2/jdk.proxy2.$Proxy237.update(Unknown Source)
  at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:425)
  ... 154 more
Caused by: java.lang.reflect.InvocationTargetException
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  at org.apache.ibatis.builder.annotation.ProviderSqlSource.invokeProviderMethod(ProviderSqlSource.java:248)
  at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:177)
  ... 176 more
Caused by: java.lang.NullPointerException: Cannot invoke "com.mybatisflex.core.table.ColumnInfo.buildTypeHandler()" because "columnInfo" is null
  at com.mybatisflex.core.table.TableInfo.buildUpdateSqlArgs(TableInfo.java:619)
  at com.mybatisflex.core.provider.EntitySqlProvider.update(EntitySqlProvider.java:239)
  ... 182 more

以上的方法都行不通。

以下是目前解决方法:

AccountDAO updateAccount = new AccountDAO(); // 不使用 UpdateEntity
updateAccount.setId(info.getId());
updateAccount.setAge(info.getAge());

// 两种方法都行
mapper.update(updateAccount); // 执行 <Mapper> 里的 <update()>
// updateById(updateAccount); // 执行 <ServiceImpl> 里的 <updateById()>

另外,不明白使用 UpdateEntity 的意义是什么,还是说需要配合 UpdateWrapper 一起使用?能够请教说明下吗?

v1.4.5版本,表名与字段名相同时编译报错

  1. 版本:v1.4.5
  2. 报错信息:
已在类 top.fenston.demo.mybatisflex.entity.table.AccountTableDef中定义了变量 ACCOUNT

报错TableDef:

package top.fenston.demo.mybatisflex.entity.table;

import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.table.TableDef;

// Auto generate by mybatis-flex, do not modify it.
public class AccountTableDef extends TableDef {

    public static final AccountTableDef ACCOUNT = new AccountTableDef("", "account");

    public QueryColumn ID = new QueryColumn(this, "id");
    public QueryColumn NAME = new QueryColumn(this, "name");
    public QueryColumn ACCOUNT = new QueryColumn(this, "account");
    public QueryColumn MONEY = new QueryColumn(this, "money");
    public QueryColumn ALL_COLUMNS = new QueryColumn(this, "*");
    public QueryColumn[] DEFAULT_COLUMNS = new QueryColumn[]{ID, NAME, ACCOUNT, MONEY};

    public AccountTableDef(String schema, String tableName) {
       super(schema, tableName);
    }
}
  1. 报错代码
    实体类:
package top.fenston.demo.mybatisflex.entity;

import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;

@Data
@Table("account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;

    @Column(value = "name")
    private String name;

    @Column(value = "account")
    private Double account;

    @Column(value = "money")
    private Double money;

}

MybatisFlexAutoConfiguration疑问

mybatis默认会创建SqlSessionFactory吧,这个bean是不是没办法初始化
图片

带来的问题就是一些配置没办法生效,例如configurationCustomizers,数据库类型读取等等

[建议&问题] Pagination分页查询功能不能支持根据条件进行分页查询或者查询所有数据?

问题:

  • 使用该分页查询功能必须提供Page或者其他参数,但如果不想要分页查询就会抛出异常。

原因:

  • 由于提供给前端的接口属于比较大众化,可根据条件去进行分页查询或者查询所有数据,但是后端处理会比较麻烦和困难。

这以前的写法,不管是使用Mapper.xml还是类似于MyBatis的Example,都是使用PageHelper来帮忙分页查询的。

public void startPage(Pagination pagination) {
   if (pagination != null) {
       if (pagination.getPageNumber() > 0) {
           PageHelper.startPage(pagination.getPageNumber(), pagination.getRowPerPage());
       }
   }
}

--- 分割线 ---

FilterUtil.startPage(filter.getPagination());

List<CategoryBean> list = customMapper.getCategoryByFilter(subFilter); // 使用了 Mapper.xml 处理查询

return Result.standardizedWithObject(list, Page.of(list)); // Page.of(list) 处理并且拿出分页数据,为了统一格式分页数据

这使用了MyBatis-Flex之后的写法,由于前面 QueryWrapper 写法非常方便,但必须使用 Page 功能,而且不支持PageHelper分页查询。

QueryWrapper query = QueryWrapper.create()
     .and(category.type.eq(FilterUtil.search(subFilter.getType())))
     .and(category.name.like(FilterUtil.search(subFilter.getName())))
     .and(category.status.eq(FilterUtil.search(subFilter.getStatus())));

// filter.getPagination().page() 是 Page<T>
Page<Category> list = categoryMapper.paginate(filter.getPagination().page(), query);

// list.getRecords() 是为了统一化格式返回数据
// list 是会处理 Page<T> 的分页数据,这也是为了统一格式分页数据,避免参数名称不一样
return Result.standardizedWithObject(list.getRecords(), list);

这代码 categoryMapper.paginate(filter.getPagination().page(), query) 如果想要查询所有数据,不管是提供null值还是其他参数都会抛出异常,目前找不到解决方法。

希望能够支持按照条件分页查询或者查询所有,如果方便的话可以提供解决方案,不然只能使用旧方法了。

另外,项目都是使用较新版本的,不管是Spring Boot,PageHelper,还是Mybatis-Flex。

非常感谢。

[建议] QueryWrapper里的orderBy能不能支持检查NULL值或者空值?

问题:

  • 只要在orderBy里提供null或者空值,就会抛出异常

原因:

  • 想要按照条件进行排序,由于是否进行排序是前端决定的,因此前端如果不需要排序的话,那么就会提供null或者空值给后端(后端收到还是会检查一次的)

想要的结果是:

     QueryWrapper query = QueryWrapper.create()
           .and(category.catType.eq(filter.getType()))
           .and(category.catName.like(filter.getName()))
           .orderBy(filter.getSort().sortBy());

filter.getSort().sortBy()会返回空值的如果前端与后端都不需要排序的话,但这样会抛出异常。


目前解决方法是:

   if (filter.getSort().canSort()) {
       query.orderBy(filter.getSort().sortBy());
   }

这导致多了一个步骤。另一个解决方法就是后端强制性添加参数进行排序,但扩展性不好。

插入更新数据报错

1.1.9版本默认继承了uuid的主键生成器 UUIDKeyGenerator
实体类主键字段注解@id(keyType=KeyType.Generator, value="uuid")

执行mapper.insertSelective(entity)时报错

Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:

Error updating database. Cause: com.mybatisflex.core.exception.MybatisFlexException: java.lang.IllegalArgumentException: object is not an instance of declaring class

Cause: com.mybatisflex.core.exception.MybatisFlexException: java.lang.IllegalArgumentException: object is not an instance of declaring class

at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:96)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441)
at com.sun.proxy.$Proxy86.insert(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:272)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62)
at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at com.sun.proxy.$Proxy90.insert(Unknown Source)
at com.mybatisflex.core.BaseMapper.insertSelective(BaseMapper.java:57)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at org.apache.ibatis.binding.MapperProxy$DefaultMethodInvoker.invoke(MapperProxy.java:159)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at com.sun.proxy.$Proxy90.insertSelective(Unknown Source)
... 57 more
Caused by: org.apache.ibatis.exceptions.PersistenceException:

Error updating database. Cause: com.mybatisflex.core.exception.MybatisFlexException: java.lang.IllegalArgumentException: object is not an instance of declaring class

Cause: com.mybatisflex.core.exception.MybatisFlexException: java.lang.IllegalArgumentException: object is not an instance of declaring class

at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:196)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:181)
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.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427)
... 68 more
Caused by: com.mybatisflex.core.exception.MybatisFlexException: java.lang.IllegalArgumentException: object is not an instance of declaring class
at com.mybatisflex.core.exception.FlexExceptions.wrap(FlexExceptions.java:37)
at com.mybatisflex.core.keygen.CustomKeyGenerator.processBefore(CustomKeyGenerator.java:76)
at org.apache.ibatis.executor.statement.BaseStatementHandler.generateKeys(BaseStatementHandler.java:141)
at org.apache.ibatis.executor.statement.BaseStatementHandler.(BaseStatementHandler.java:63)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.(PreparedStatementHandler.java:41)
at com.mybatisflex.core.mybatis.FlexPreparedStatementHandler.(FlexPreparedStatementHandler.java:38)
at com.mybatisflex.core.mybatis.FlexStatementHandler.(FlexStatementHandler.java:57)
at com.mybatisflex.core.mybatis.FlexConfiguration.newStatementHandler(FlexConfiguration.java:100)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194)
... 74 more
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
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.apache.ibatis.reflection.invoker.MethodInvoker.invoke(MethodInvoker.java:44)
at com.mybatisflex.core.keygen.CustomKeyGenerator.processBefore(CustomKeyGenerator.java:74)
... 84 more

使用QueryWrapper时返回值建议

QueryWrapper query = QueryWrapper.create()
        .select(ACCOUNT.ID)
        .from(ACCOUNT);
List<Account> result = mapper.selectListByQuery(query);
        

期望返回 List<Long>,或者一个自定义对象,而非不全的Account

整合 solon+postgresql的一些问题

  1. Column 自定义 typeHandler 会出现 Cannot invoke "org.apache.ibatis.session.Configuration.getTypeHandlerRegistry()" because "configuration" is null 的问题
    image
    我看了solon-plugin 没有发现设置defaultConfig的地方,我修改了插件,
    image
    可以正常运行
  2. 我定义了逻辑删除的字段为bool类型,正常查询的时候没有问题,如果通过主键查询会出现sql错误,我查找了一下是方言问题
    image
    格式化出来是 "xxxx" 这个在postgresql是无法执行的

代码生成是否应该支持日期时间数据类型的选择

比如定义了一个一类只需要日期,不需要时间,有一列日期时间都需要,当前测试
image

一个使用了Date,一个使用了LocalDateTime,这块最好还是能够支持配置,选择需要的类型。

漏看了文档 ~~

JdbcTypeMapping.registerMapping(LocalDate.class, Date.class)

可以实现,抱歉,关闭了。

使用Generator生成表entity时,对entity的列设置typeHandler无效。

使用代码生成器生产entity时,如下的写法会导致typeHandler不生成

ColumnConfig columnConfig = globalConfig.getColumnConfig(tableName, fieldName);
columnConfig.setTypeHandler(EncryptHandlerField.class);

因为源码com.mybatisflex.codegen.config.StrategyConfig里101行

 if (columnConfig == null && columnConfigMap != null) {
            columnConfig = columnConfigMap.get(columnName);
        }

        if (columnConfig == null) {
            columnConfig = new ColumnConfig();
        }
      ....
return columnConfig;

columnConfig 在columnConfigMap拿不到为空时,会自动new,但是没有放入map导致

selectXXXByQueryAs方法结果映射错误

当两个表中有同名的字段时,使用selectXXXByQueryAs方法有一方会映射失败
比如

public class User implements Serializable {

@Id(value = "id", keyType = KeyType.Auto)
private Integer id;

@Column("name")
private String name;

@Column("age")
private Integer age;

private List<Book> books;

}

public class Book implements Serializable {

@Id(value = "id", keyType = KeyType.Auto)
private Integer id;

@Column("name")
private String name;

@Column("user_id")
private Integer userId;

}

    QueryWrapper queryWrapper = QueryWrapper
            .create()
            .select(USER.ALL_COLUMNS,BOOK.ALL_COLUMNS)
            .from(USER).as("u")
            .join(BOOK).as("b")
            .on(USER.ID.eq(BOOK.USER_ID))
            .where(USER.NAME.eq("sui"));
    User user = userMapper.selectOneByQueryAs(queryWrapper, User.class);

这段代码运行结果中,user对象映射的books列表中,id 和 name这两个字段会映射失败,因为同名了,使用selectWithRelations可以正常映射,但是这个方法会进行二次查询,对性能会有影响,有什么解决办法吗

逻辑删除改进

能不能像mp一样,全局配置一个逻辑删除的字段名,只要实体类里有这个字段,就是逻辑删除?
image

必须吐槽的一个问题

try {
            var a = LambdaUtil.getFieldName(Account::getId);
            System.out.println(a);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        try {
            var b = LambdaUtil.getFieldName(new LambdaGetter<Account>() {
                @Override
                public Object get(Account source) {
                    return source.getId();
                }
            });
            System.out.println(b);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        try {
            var c = LambdaUtil.getFieldName((LambdaGetter<Account>) source -> source.getId());
            System.out.println(c);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

b写法,经idea一次优化为c,在经idea优化一次为a,但是三种写法,执行结果不一样

@EnumValue 注解功能缺陷

public enum UserType {
    ADMIN,
    USER,
    MERCHANT,
    ;
}

如果一个enum没有自定义字段的情况,如何使用@EnumValue,或者可以提供一个接口实现?

文档链接

code generator error

version

mybatis-flex version:1.3.0
mybatis-flex-codegen version:1.3.5
springboot verison:2.7.12

The POM is as follows

<dependency>
            <groupId>com.mybatis-flex</groupId>
            <artifactId>mybatis-flex-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.mybatis-flex</groupId>
            <artifactId>mybatis-flex-processor</artifactId>
            <version>1.3.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>4.0.3</version>
        </dependency>

        <dependency>
            <groupId>com.mybatis-flex</groupId>
            <artifactId>mybatis-flex-codegen</artifactId>
            <version>1.3.5</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
            <version>8.0.32</version>
        </dependency>

issue:

An error is reported when the code generator generates the implementation class, and the default template of the implementation class is null。

The code generator code is as follows

public class Codegen {
    public static void main(String[] args) {
        //配置数据源
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/fed_portal?characterEncoding=utf-8");
        dataSource.setUsername("portal");
        dataSource.setPassword("fed_portal");
        //创建配置内容,两种风格都可以。
        GlobalConfig globalConfig = createGlobalConfigUseStyle2();
        //通过 datasource 和 globalConfig 创建代码生成器
        Generator generator = new Generator(dataSource, globalConfig);
        //生成代码
        generator.generate();
    }
    public static GlobalConfig createGlobalConfigUseStyle2() {
        //创建配置内容
        GlobalConfig globalConfig = new GlobalConfig();
        //设置根包
        globalConfig.getPackageConfig()
                .setSourceDir("E://2023/mybatis-flex")
                .setBasePackage("com.tech.fate.portal.web");
        //设置表前缀和只生成哪些表
        globalConfig.getStrategyConfig()
                .setGenerateTable("project_participant");
        //设置生成 entity 并启用 Lombok
        globalConfig.enableEntity()
                .setWithLombok(true);
        //设置生成 mapper
        globalConfig.enableMapper();
        globalConfig.enableController();
        globalConfig.enableService();
        globalConfig.enableServiceImpl();
        return globalConfig;
    }
}

The console error log is as follows:

com.jfinal.template.TemplateException: null
Template: "/templates/enjoy/serviceImpl.tpl". Line: 1
	at com.jfinal.template.expr.ast.Field.eval(Field.java:86)
	at com.jfinal.template.expr.ast.Assign.assignVariable(Assign.java:102)
	at com.jfinal.template.expr.ast.Assign.eval(Assign.java:95)
	at com.jfinal.template.stat.ast.Set.exec(Set.java:57)
	at com.jfinal.template.stat.ast.StatList.exec(StatList.java:68)
	at com.jfinal.template.Template.render(Template.java:57)
	at com.mybatisflex.codegen.template.impl.EnjoyTemplate.generate(EnjoyTemplate.java:51)
	at com.mybatisflex.codegen.generator.impl.ServiceImplGenerator.generate(ServiceImplGenerator.java:73)
	at com.mybatisflex.codegen.Generator.generate(Generator.java:67)
	at com.tech.fate.portal.web.commons.Codegen.main(Codegen.java:41)
Caused by: java.lang.reflect.InvocationTargetException
	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 com.jfinal.template.expr.ast.FieldGetters$IsMethodFieldGetter.get(FieldGetters.java:130)
	at com.jfinal.template.expr.ast.Field.eval(Field.java:81)
	... 9 more
Caused by: java.lang.NoClassDefFoundError: com/mybatisflex/spring/service/impl/CacheableServiceImpl
	at com.mybatisflex.codegen.config.ServiceImplConfig.isCacheExample(ServiceImplConfig.java:127)
	... 15 more
Caused by: java.lang.ClassNotFoundException: com.mybatisflex.spring.service.impl.CacheableServiceImpl
	at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
	... 16 more

如何关闭 banner?

如标题所示, 请问要怎么关闭? 在 MybatisFlexProperties 中没有找到相关的配置

mybatis-flex v1.4.3 版本 数据库表定义了唯一性约束 不会抛出DuplicateKeyException异常的问题

  1. 版本: v1.4.3
  2. 简要代码:
sysUserMapper.insertSelective(createUserDAO);
  1. 异常信息
java.lang.reflect.UndeclaredThrowableException
	at jdk.proxy2/jdk.proxy2.$Proxy119.insertSelective(Unknown Source)
	at cn.demo.admin.service.sys.impl.SysUserServiceImpl.addUser(SysUserServiceImpl.java:94)
	at cn.demo.admin.service.sys.impl.SysUserServiceImplTest.add(SysUserServiceImplTest.java:42)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
	at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at com.mybatisflex.core.mybatis.MapperInvocationHandler.invoke(MapperInvocationHandler.java:74)
	... 73 more
Caused by: org.springframework.dao.DuplicateKeyException: 
### Error updating database.  Cause: java.sql.SQLIntegrityConstraintViolationException: (conn=28) Duplicate entry 'test_account-0--1' for key 'uk_username'
### The error may exist in cn/demo/data/domain/sys/mapper/SysUserMapper.java (best guess)
### The error may involve cn.demo.data.domain.sys.mapper.SysUserMapper.insert
### The error occurred while executing an update
### SQL: INSERT INTO `sys_user`(`dept_id`, `user_name`, `nick_name`, `password`, `status`, `sex`, `post_id`, `remark`, `email`, `mobile`, `create_id`, `update_id`, `gmt_create`, `gmt_modified`, `del_flag`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
### Cause: java.sql.SQLIntegrityConstraintViolationException: (conn=28) Duplicate entry 'test_account-0--1' for key 'uk_username'
; (conn=28) Duplicate entry 'test_account-0--1' for key 'uk_username'
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:251)
	at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70)
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:92)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:439)
	at jdk.proxy2/jdk.proxy2.$Proxy115.insert(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:272)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62)
	at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:142)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
	at jdk.proxy2/jdk.proxy2.$Proxy119.insert(Unknown Source)
	at com.mybatisflex.core.BaseMapper.insertSelective(BaseMapper.java:61)
	at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
	at org.apache.ibatis.binding.MapperProxy$DefaultMethodInvoker.invoke(MapperProxy.java:155)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
	at jdk.proxy2/jdk.proxy2.$Proxy119.insertSelective(Unknown Source)
	... 78 more
Caused by: java.sql.SQLIntegrityConstraintViolationException: (conn=28) Duplicate entry 'test_account-0--1' for key 'uk_username'
	at org.mariadb.jdbc.export.ExceptionFactory.createException(ExceptionFactory.java:290)
	at org.mariadb.jdbc.export.ExceptionFactory.create(ExceptionFactory.java:370)
	at org.mariadb.jdbc.message.ClientMessage.readPacket(ClientMessage.java:134)
	at org.mariadb.jdbc.client.impl.StandardClient.readPacket(StandardClient.java:872)
	at org.mariadb.jdbc.client.impl.StandardClient.readResults(StandardClient.java:811)
	at org.mariadb.jdbc.client.impl.StandardClient.readResponse(StandardClient.java:730)
	at org.mariadb.jdbc.client.impl.StandardClient.execute(StandardClient.java:654)
	at org.mariadb.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:95)
	at org.mariadb.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:268)
	at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:483)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:48)
	at com.mybatisflex.core.mybatis.FlexStatementHandler.lambda$update$1(FlexStatementHandler.java:94)
	at com.mybatisflex.core.audit.AuditManager.startAudit(AuditManager.java:103)
	at com.mybatisflex.core.mybatis.FlexStatementHandler.update(FlexStatementHandler.java:94)
	at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
	at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:184)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:425)
	... 89 more

请问下这个怎么做才能抛出DuplicateKeyException异常啊

QueryWrapper 是否能添加 clear() 方法

如标题所示, 当在一个方法中多次调用时, 可以复用 QueryWrapper

public void xx() {
    QueryWrapper query1 = QueryWrapper.create().select(Tables....);
    ...
    QueryWrapper query2 = QueryWrapper.create().select(Tables....);
    ...
    QueryWrapper query3 = QueryWrapper.create().select(Tables....);
}

支持成可以像下面这样

public void xx() {
    QueryWrapper query = QueryWrapper.create().select(Tables....);
    ...
    query.clear();
    query.select(Tables....);
    ...
    query.clear().select(Tables....);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.