Both fish and bear's paw: use JPA and Mybatis at the same time

Preface

The argument between JPA and Mybatis has been around for a long time. I still remember that 2 years ago, I expressed my opinion on the topic of the two in the spring4all community. I was supporting JPA at the time. Of course, this is related to my familiarity with JPA. , But there are also deep reasons, that is, the design concept of JPA fits the idea of ​​domain-driven design, which can guide us to design database interaction interfaces. In the past two years of work, I have gradually come into contact with some projects that use Mybatis, and I have gained a certain new understanding of it. It is said that cognition is a spiraling process. With the accumulation of experience, people will easily overthrow the past. Today, two years later, I also have a new perspective. This article is not to tell you who is better between JPA and Mybatis, but to try to seek common ground while reserving differences, and even use JPA and Mybatis in the project. what? Is it necessary to use two ORM frameworks at the same time? Don't rush me, hope that after reading this article, you can also consider using these two frameworks in some situations.

ps. The JPA discussed in this article refers specifically to spring-data-jpa.

Modeling

@Entity
@Table(name = "t_order")
public class Order {
    
    
  
  @Id
  private String oid;
  
  @Embedded
  private CustomerVo customer;
  
  @OneToMany(cascade = {
    
    CascadeType.ALL}, orphanRemoval = true, fetch = FetchType.LAZY, mappedBy = "order")
  private List<OrderItem> orderItems;
}

The biggest feature of JPA is sqlless. As the above entity definition, it associates the database table with the type in Java. JPA can automatically create the table structure according to the @Entity annotation; based on the Repository interface implemented by this entity, This makes it easy for JPA users to implement CRUD of data. Therefore, people rarely mention "database design" in projects using JPA, and people are more concerned with domain modeling rather than data modeling.

<generatorConfiguration>
    <context id="my" targetRuntime="MyBatis3">
      
      <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL=""
           userId="" password=""/>

      <javaModelGenerator targetPackage="" targetProject="" />

      <sqlMapGenerator targetPackage="" targetProject="" />

      <javaClientGenerator targetPackage="moe.cnkirito.demo.mapper" />
      
      <table tableName="t_order" domainObjectName="Order" />


    </context>
</generatorConfiguration>

Mybatis users mostly use reverse engineering. For example, the mybatis-generator plug-in can directly translate the table structure into mapper files and entity files according to the above xml configuration.

There is no difference between code first and table first in terms of results. The difference is the process, so a well-designed system will not be judged just because of this difference, but from the point of view of guidance, there is no doubt that when designing a system, What should be considered is the relationship between entities and entities, entities and value objects, and the division of domain boundaries, rather than focusing on the design of the database table structure first.

From a modeling perspective, JPA's domain modeling ideas are even better.

Data update
Talking about the database is naturally inseparable from CRUD, let's first look at the data update operations of adding, deleting, and modifying, and see what are the general habits of the two frameworks.

The data update advocated by JPA has only one paradigm, which is divided into three steps:

First findOne is mapped to an entity, the entity
is modified in memory, the entity is saved
as a whole,
you may refute me that @Query also has nativeQuery and JPQL usage, but this is not the mainstream usage. JPA especially emphasizes the idea of ​​"overall save", which is inseparable from the statefulness emphasized by domain-driven design, that is, it believes that modification should not be directed to a certain field: "update table set a=b where colomonA=xx", It should be reflected as the change of the entity, and save represents the final persistence of the entity state.

Find first and then save obviously also applies to Mybatis, and the flexibility of Mybatis makes its data update method more diverse. Passer-by can think that JPA adheres to conventions and does not understand flexibility, and that Mybatis is unruly and indulgent and loves freedom; Passer-by can also think that the JPA format specification is easy to maintain, and Mybatis is not well-rounded. No more judgments on this point, let posters say.

In terms of personal habits, I still prefer the habit of finding first and then saving as a whole. It is not that this is a JPA patent, which Mybatis does not possess; it is the mandatory of JPA that gives me this habit.

From the perspective of data update, JPA enforces the use of find+save, and mybatis can also do this. Winner: none.

Data query
The query methods provided by JPA are mainly divided into two types

Simple query: findBy + attribute name
Complex query: JpaSpecificationExecutor
simple query provides great convenience in some simple business scenarios. FindBy + attribute name can be automatically translated into sql. If you can write less code, who is not willing What?

Complex query is the solution provided by JPA in order to solve complex query scenarios. It just converts some aggregate functions and connection operations of the database into Java methods. Although sqlless is achieved, the code written is stinky and long. It is not necessarily easy to read and maintain. This is my least favorite part of JPA, but there is no other way to solve complex queries.

And Mybatis can execute arbitrary query sql, flexibility is incomparable to JPA. The two most frequently searched questions in the database:

How to do database paging and how to do
conditional query

Mybatis can be easily solved.

Don't deny complex queries: scenarios such as aggregate queries and Join queries. The easiest way to drive a JPA user crazy is to give him a case of complex queries.

select a,b,c,sum(a) where a=xx and d=xx group by a,b,c;

Come on, show. Maybe JPA can indeed complete the above-mentioned sql escape, but you must know that not all developers are JPA experts. No one cares how complex query statements you solve with JPA. More people are concerned about whether you can put this before get off work Complicated inquiries are done, go home early.

Back to the analysis of complex data query requirements. We assume that the requirements are reasonable. After all, the complexity of the project is difficult to estimate. There may be 1,000 data query requirements that JPA can easily implement, but there are so few complex queries that JPA hold cannot hold. At this time, you can only write sql obediently. If there is another conditional query scene at this time, if else appears, it means that even @Query cannot be used, and it completely degenerates into the era of JdbcTemplate.

Then why not use Mybatis? Mybatis users have never entangled with complex queries, it is simply born for it.

Nowadays, many Mybatis plug-ins can also help users quickly generate basic methods. Although it still needs to write sql, it is not a difficult task for developers.

Don't question the possibility of JOIN operations and aggregation functions under high concurrency. In the data query scenario, Mybatis wins.

Performance In
essence, the ORM framework does not have a distinction in performance, because in the end it is converted into sql and handed over to the database engine to execute. The performance loss at the ORM level is almost negligible.

But starting from reality, Mybatis provides developers with a higher degree of SQL freedom, so it will be more flexible in some scenarios that require SQL tuning.

Maintainability
We mentioned earlier that JPA loses the freedom of SQL compared to Mybatis, and everything must be traded off. From another perspective, it provides a high-level abstraction and tries to use a unified model to solve data-level problems. . At the same time, sqlless also shields the implementation of the database and shields the compatibility issues of the high and low versions of the database, which provides great convenience for possible database migration and database upgrades.

Using both at the same time,
I will not analyze the other details. I believe there are still many points that can be used for comparison, but I believe that the main points should be mentioned above. The comparison of the above dimensions is not my original intention to write this article, but more to provide some reference suggestions for everyone to use these two frameworks from a practical development perspective.

In most scenarios, I am accustomed to using JPA. For example, when designing domain objects, thanks to the positive model of JPA, I will give priority to the relevance of entities and value objects and the boundaries of the domain context instead of paying too much attention to how to go. Design the table structure; in addition, deletion, modification and simple query scenarios, the API provided by JPA is already a paradigm engraved in my DNA, and it is very comfortable to use.

In complex query scenarios, such as

Contains join queries that do not have domain associations,
complex queries that include multiple aggregate functions, and
other queries that are more difficult to implement in JPA.
I would choose to use Mybatis, which is a bit like using Mybatis as a database view generator. Unshakable JPA fans may question the authenticity of the existence of these scenarios and whether they are design loopholes, but based on experience, even if it is a short-term solution, these scenarios exist objectively, so listen to me , Try to hug Mybatis.

With the popularity of various storage middlewares, such as mongodb and ES, replacing part of the database status, under rethinking, they are essentially using professional tools to solve problems in specific scenarios, and the ultimate goal is to liberate productivity. As the oldest and most basic storage component, the database does carry a lot of things that it shouldn't bear. So why let a tool or a framework become a gap that limits our imagination?

In fact, the two frameworks are not heavy. With the support of springboot, the coexistence of the two can be achieved by introducing a few lines of configuration.

I have used both in my recent project, and I followed the specifications discussed earlier in this article. I also recommend it to you, so you might as well try.

Learn Java with zero foundation, and recommend a personal Java learning corner .

Guess you like

Origin blog.csdn.net/weixin_49794051/article/details/111903009