A preliminary FluentMybatis

By chance, THE Nuggets saw Fluent MyBatis using the primer.

In fact, I have been looking for an ORM framework that can completely do not need to write SQL. Now I am using Mybatis-Plus in my work, but Mybatis-Plus does not support multi-table join query, multiple tables can only write SQL.

It’s not that I hate writing SQL, but Idea doesn’t check XML as rigorously as it does Java code. So it’s easy to make small mistakes, sometimes only to discover them after release, and then change the release, wasting time.

Then I found FluentMybatis, which was quite a surprise at the beginning.

Then I spent the day looking at it.

I’ll give you a rundown.

Rely on

<dependency>
    <groupId>com.github.atool</groupId>
    <artifactId>fluent-mybatis</artifactId>
    <version>1.4.1</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.github.atool</groupId>
    <artifactId>fluent-mybatis-processor</artifactId>
    <version>1.4.1</version>
    <scope>provided</scope>
</dependency>
<! -- Code generator -->
<dependency>
    <groupId>com.github.atool</groupId>
    <artifactId>generator</artifactId>
    <version>1.0.2</version>
</dependency>
<! -- Connection pool -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.5.0</version>
</dependency>
Copy the code

If a code generator is used, add a code generator dependency. The FileGenerator class is not found. The connection pool used in the example is DBCP2.

Code generator

FluentMybatis also has code generators, but not the same as Mybatis-Plus. Mybatis-Plus requires the use of templates such as Freemaker. The generated code is more complete, from Domain to Controller, and the configuration is more flexible; Suffix, package name, path, author, and AR mode can be configured, which is more in line with the three-tier architecture concept.

FluentMybatis configuration is not so flexible, it can be said that there is basically no configuration, specify a good database, path, table name is finished. The annotation mode is as follows:

public class AppEntityGenerator {

    static final String url = "jdbc:mysql://localhost:3306/fluent_mybatis_demo? useSSL=false&useUnicode=true&characterEncoding=utf-8";

    public static void main(String[] args) {
        FileGenerator.build(Abc.class);
    }

    @tables (/** database connection info **/ url = url, username = "root", password = "password", /** Entity class parent package path **/ basePack = "com.ler.demo", /** Entity code source directory **/ srcDir = "/ SRC /main/ Java ", DaoDir = "/ SRC /main/ Java ", /** daoDir = "/ SRC /main/ Java" **/ gmtCreated = "gmT_create ", gmtModified =" gmT_modified ", logicDeleted = "is_deleted", /** tables = @table (value = {"student_score","student","county_division"})
    static class Abc {}}Copy the code

Or use the entity-class pattern

public class EntityGeneratorDemo {

    static final String url = "jdbc:mysql://localhost:3306/fluent_mybatis_demo? useSSL=false&useUnicode=true&characterEncoding=utf-8";

    public static void main(String[] args) throws Exception {

        FileGenerator.build(true.false)
                .globalConfig(g -> g
                        /** Set the SRC/Java path **/
                        .setOutputDir("src/main/java/")
                        /** Set package **/
                        .setBasePackage("com.ler.demo")
                        //.setDaoPackage("com.ler.demo.service")
                        /** Set up database connection **/
                        .setDataSource(url, "root"."password")
                )
                .tables(t -> t
                                /** Sets the table that needs to generate the Entity class **/
                                .table("your_table1")
                        //.table(" other table ")
                        //.table(" other table ")) .execute(); }}Copy the code

It’s a little bit simpler, but the flexibility is gone. FluentMybatis doesn’t use templates. It uses JavaPoet.

JavaPoet

Making address javapoet

JavaPoet is an open source programming framework for code generation, which makes it easy to generate.java files. If you’re interested, you can do some research. It’s interesting. FluentMybatis uses Javapoet.

<dependency>
    <groupId>com.squareup</groupId>
    <artifactId>javapoet</artifactId>
    <version>1.13.0</version>
</dependency>
Copy the code








JavaPoet aside, there are plenty of blogs on the web about it. Today just a preliminary look at FluentMybatis.

As for the code generator, she generates three files, the Domain entity class, the Dao interface, and the DaoImpl implementation class. DaoImpl = ServiceImpl Dao = Service DaoImpl = ServiceImpl Dao = Service DaoImpl It would be nice if the package name, suffix and author could be customized. Service is more pleasing to the eye after watching it for a long time.

Annotation Processor

FluentMybatis another bright spot is Mapper file management. Mybatis-Plus generates Mapper interface files as well as XML files, because it does not support multi-table queries, so sometimes complex queries require us to write SOME SQL in XML (annotations in the interface can also write SQL).

However, FluentMybatis supports no matter how complex SQL, so her Mapper file is not exposed.

She uses the Annotation Processor to generate the files needed for database operations during compilation, including BaseDao, Mapper, Helper, Warpper, Entity, etc. If the table adds new fields, it only needs to be recompiled. The relationship between the user and the Dao is completely shielded, simplifying the persistence layer.

Java annotation processor, this article is good, want to know can see.

So programmers don’t have to worry about the persistence layer, just the Service and Controller. At a stroke, the project structure was simplified and much clearer.

The joining together of SQL

Although this is a first look, let’s briefly explain how to use code to concatenate SQL.

FluentMybatis aims to support all kinds of SQL, no matter how complex it is, as long as it can be written, it can be spelled. See the documentation for examples, so it’s a bit more complicated than Mybatis-Plus.

I’ll just write a few of them. They’re all copied from the documentation. For details, you can go to the documentation Gitee address documentation.

Nested query:

SELECT * FROM student
     WHERE is_deleted = ?
     AND grade = ?
     AND home_county_id IN
     (SELECT id FROM county_division WHERE is_deleted = ? AND province = ? AND city =?).Copy the code

The corresponding Java code:

StudentQuery query = new StudentQuery()
            .where.isDeleted().isFalse()
            .and.grade().eq(4)
            .and.homeCountyId().in(CountyDivisionQuery.class, q -> q
                    .selectId()
                    .where.isDeleted().isFalse()
                    .and.province().eq(Zhejiang Province)
                    .and.city().eq("Hangzhou")
                    .end()
            ).end();
List<StudentEntity> students = studentMapper.listEntity(query);
Copy the code

The EXISTS functions:

SELECT * FROM student
    WHERE is_deleted = ?
    AND EXISTS (SELECT id FROM student_score
        WHERE is_deleted = ?
        AND school_term = ?
        AND score < ?
        AND subject IN (?, ?)
        AND student_id =student.id)
Copy the code

The corresponding Java code:

StudentQuery query = new StudentQuery()
            .where.isDeleted().isFalse()
            .and.exists(StudentScoreQuery.class, q -> q
                    .selectId()
                    .where.isDeleted().isFalse()
                    .and.schoolTerm().eq(2019)
                    .and.score().lt(60)
                    .and.subject().in(new String[]{"Chinese"."Mathematics"})
                    .and.studentId().apply("= student.id")
                    .end()
            ).end();
List<StudentEntity> students = studentMapper.listEntity(query);
Copy the code

The JOIN operation:

SELECT t1.user_name, t3.subject, t3.score
    FROM student t1
    JOIN county_division t2 ON t1.home_county_id = t2.id
    JOIN student_score t3 ON t1.id = t3.student_id
    WHERE t1.is_deleted = ?
    AND t2.is_deleted = ? AND t2.province = ? AND t2.city = ?
    AND t3.is_deleted = ? AND t3.school_term = ? AND t3.subject IN (?, ?) AND t3.score > = ?
Copy the code

The corresponding Java code:

Parameters parameters = new Parameters();
IQuery query = JoinBuilder
        .<StudentQuery>from(new StudentQuery("t1", parameters)
                .select.userName().end()
                .where.isDeleted().isFalse().end())
        .join(new CountyDivisionQuery("t2", parameters)
                .where.isDeleted().isFalse()
                .and.province().eq(Zhejiang Province)
                .and.city().eq("Hangzhou").end())
        .on(l -> l.where.homeCountyId(), r -> r.where.id()).endJoin()
        .join(new StudentScoreQuery("t3", parameters)
                .select.subject().score().end()
                .where.isDeleted().isFalse()
                .and.schoolTerm().eq(2019)
                .and.subject().in(new String[]{"Chinese"."Mathematics"})
                .and.score().ge(90).end())
        .on(l -> l.where.id(), r -> r.where.studentId()).endJoin()
        .build();
studentMapper.listMaps(query);
Copy the code

JOIN and OR operations:

SELECT t1.user_name, t3.subject, t3.score
    FROM student t1
    JOIN county_division t2 ON t1.home_county_id = t2.id
    JOIN student_score t3 ON t1.id = t3.student_id
    WHERE t1.is_deleted = ?
    AND t2.is_deleted = ? AND t2.province = ? AND t2.city = ?
    AND t3.is_deleted = ? AND t3.school_term = ?
    AND ( subject = ? OR subject =?).AND t3.score > = ?
Copy the code

The corresponding Java code:

Parameters parameters = new Parameters();
IQuery query = JoinBuilder
        .<StudentQuery>from(new StudentQuery("t1", parameters)
                .select.userName().end()
                .where.isDeleted().isFalse().end())
        .join(new CountyDivisionQuery("t2", parameters)
                .where.isDeleted().isFalse()
                .and.province().eq(Zhejiang Province)
                .and.city().eq("Hangzhou").end())
        .on(l -> l.where.homeCountyId(), r -> r.where.id()).endJoin()
        .join(new StudentScoreQuery("t3", parameters)
                .select.subject().score().end()
                .where.isDeleted().isFalse()
                .and.schoolTerm().eq(2019)
                .and(iq -> iq
                        .where.subject().eq("Chinese")
                        .or.subject().eq("Mathematics").end())
                .and.score().ge(90).end())
        .on(l -> l.where.id(), r -> r.where.studentId()).endJoin()
        .build();
studentMapper.listMaps(query);
Copy the code

And I’m just going to give you an example, just so you can write it down later when you forget how to put it together.

conclusion

In the development of technology, FluentMybatis used some things I also heard for the first time. Although some places are quite advanced and do not need to write SQL at all, the way the above concatenated SQL is not that easy to use.

Although it is a little difficult to use, but skilled than Mybatis-Plus good.

Radish cabbage each has his love, the most suitable is the best, but also depends on the company’s technical route.

The last

Did not write for a long time, it is to do not have what good material, 2 it is oneself also compare lazy, newest like to play game again, this drag is a much month, sin sin! I want to study hard in the future.

Finally, welcome everyone to pay attention to my public number, learn together, progress together. Refueling 🤣