introduction
When we talk about the word “persistence”, we must be familiar with the word “persistence”.
In the process of persistence, there are two giants that attract the attention of developersHibernate
AndMyBatis
Many developers often compare the two. goGoogle
On, are similar to the two articles contrast each other.
Hibernate
AndMyBatis
It’s likejava
andphp
Similarly, there seems to be a fight between the two sides.
Although I am using itHibernate
But I don’t deny itMyBatis
, both are excellent, but everything is business priority.
After learning Mr. Pan’s “springboot + angular introductory example tutorial”, I also thought of the most originalJDBC
。
Today, we will talk about the evolution and comparison of Persistence technology from ancient times to the present.
Persistence
JDBC in ancient times
JDBC
:Java Database Connectivity
, abbreviated asJDBC
。 yesJava
The application program interface (API) is used to regulate how the client program accesses the database, and provides methods such as querying and updating the data in the database.JDBC
It is oriented to relational database.
EveryoneJava
Programmers may all have experiencedJDBC
Fear of domination.
Here I amJava
It was written in the lab classJDBC
Code, the implementation of the function is very simple, is to put aStudent
Object is saved to thestudent
In the table.
/**
*Persistent student entity
*/
private static void persistStudent(Student student) {
try {
Class.forName("com.mysql.jdbc.Driver");
//Database connection configuration
String url = "jdbc:mysql://127.0.0.1:7777/java?characterEncoding=utf-8";
//Get connection
Connection connection = DriverManager.getConnection(url, "root", "root");
//Get statement
Statement statement = connection.createStatement();
//Generate SQL statement
String SQL = student.toSQLString();
//Execute statement
statement.executeUpdate(SQL);
} catch (SQLException e) {
System.out.println("ERROR: " + e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println("ERROR: " + e.getMessage());
} finally {
statement.close();
connection.close();
}
}
The core function is actually one line:statement.executeUpdate(SQL)
I just want to implement oneINSERT
Statement to ensure data persistence.
But in theJDBC
But you need to implement loadingMySQL
Drive, getConnection
, getStatement
Can be executedSQL
After execution, you need to release resources manually, which is not a problem.
Programmers hate to write repetitive code, just like I feel it is boring to transplant duplicate code from huasoft platform to test platform, so these “template” code needs to be encapsulated.
Encapsulation tool class
We are all ordinary people. What we can think of must have been thought of for a long time.
Spring
PackagedJDBC
, providesJdbcTemplate
。
Another famous one isApache
EncapsulatedDBUtils
。
UsedJdbcTemplate
After that, we don’t need to write a templateConnection
、Statement
、try ... catch ... finally
And so on. TheJdbcTemplate
Query the teacher table. The code length is as follows:
@GetMapping
public List<Teacher> getAll() {
/*Initializes an array of variable sizes*/
List<Teacher> teachers = new ArrayList<>();
/*Defines the object that implements the rowcallbackhandler interface*/
RowCallbackHandler rowCallbackHandler = new RowCallbackHandler() {
/**
*This method is used to execute jdbcTemplate.query After the callback, each line of data callback once. For example, if there are two rows of data in the teacher table, call back this method twice.
*
*@ param resultset query results, one line at a time
*When an error occurs in the @ throws sqlexception query, this exception will be thrown and will not be handled for the time being.
*/
@Override
public void processRow(ResultSet resultSet) throws SQLException {
Teacher teacher = new Teacher();
/*Get the field ID and convert it to long type*/
teacher.setId(resultSet.getLong("id"));
/*Get the field name and convert it to string type*/
teacher.setName(resultSet.getString("name"));
/*Get the field sex and convert it to boolean type*/
teacher.setSex(resultSet.getBoolean("sex"));
teacher.setUsername(resultSet.getString("username"));
teacher.setEmail(resultSet.getString("email"));
teacher.setCreateTime(resultSet.getLong("create_time"));
teacher.setUpdateTime(resultSet.getLong("update_time"));
/*Add the resulting teacher to the array to be returned*/
teachers.add(teacher);
}
};
/*Define query string*/
String query = "select id, name, sex, username, email, create_time, update_time from teacher";
/*Use query to query, and the result of the query is called rowCallbackHandler.processRow The () method is passed to the rowcallbackhandler object*/
jdbcTemplate.query(query, rowCallbackHandler);
return teachers;
}
Thinking: since it can be passedResultSet
Get the results here, whySpring
Encapsulatedquery
Method does not return directlyResultSet
What about designing such a callback object?
Tips,JdbcTemplate
The core source code of the query is as follows:
@Override
@Nullable
public T doInStatement(Statement stmt) throws SQLException {
ResultSet rs = null;
try {
rs = stmt.executeQuery(sql);
return rse.extractData(rs);
}
finally {
JdbcUtils.closeResultSet(rs);
}
}
ResultSet
It’s annoying to use, isn’t it? You need to manually get the field and set it into the object,JdbcTemplate
It improves the development efficiency, but the improvement is not obvious. Can it be simpler?
ORM
In order to avoid writing a large number of such business independent code, theORM
Thought.
teacher.setName(resultSet.getString("name"));
teacher.setSex(resultSet.getBoolean("sex"));
teacher.setUsername(resultSet.getString("username"));
teacher.setEmail(resultSet.getString("email"));
ORM
: object relation mapping. By associating objects with data tables, we don’t need to pay attention to the redundant code of uncorrelated business, namely operation data table.
Semi automatic ORM
Semi automaticORM
Frames are hotMyBatis
。
I simply went to learn the followingMyBatis
After all, there must be a reason for so many companies to use it. If they are good enough, they can also consider using it. But the results were somewhat disappointing.
Open the official website to learn. This should be considered as the most humble official website of the famous open source framework I have ever seen. The content in it is not detailed.
The examples on the official website are not detailed enough. I have read many moreMyBatis
To learn.
Open the configuration of database field underline to object named hump.
mybatis.configuration.map-underscore-to-camel-case=true
Or the classic relationship among teachers, classes and students
public class Teacher {
private Long id;
private String name;
private Boolean sex;
private String username;
private String email;
private Long createTime;
private Long updateTime;
}
public class Klass {
private Long id;
private String name;
private Teacher teacher;
private List<Student> students;
}
public class Student {
private Long id;
private String name;
}
Teacher’sCRUD
Single table query:
@Mapper
public interface TeacherMapper {
@Select("SELECT * FROM teacher")
List<Teacher> getAll();
@Select("SELECT * FROM teacher WHERE id = #{id}")
Teacher get(Long id);
@Select("SELECT * FROM teacher WHERE username = #{username}")
Teacher findByUsername(String username);
@Insert("INSERT INTO teacher(name, sex, username, email, create_time, update_time) VALUES(#{name}, #{sex}, #{username}, #{email}, #{createTime}, #{updateTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(Teacher teacher);
@Update("UPDATE teacher SET name=#{name}, sex=#{sex}, email=#{email}, update_time=#{updateTime} WHERE id=#{id}")
void update(Teacher teacher);
@Delete("DELETE FROM teacher WHERE id=#{id}")
void delete(Long id);
}
Associated query:
@Mapper
public interface KlassMapper {
@Select("SELECT * FROM klass")
@Results({
@Result(column = "teacher_id", property = "teacher", one = @One(select = "club.yunzhi.mybatis.mapper.TeacherMapper.get")),
@Result(column = "id", property = "students", many = @Many(select = "club.yunzhi.mybatis.mapper.StudentMapper.getAllByKlassId"))
})
List<Klass> getAll();
}
Used in associationStudentMapper
Subquery:
@Mapper
public interface StudentMapper {
@Select("SELECT * FROM student WHERE klass_id=#{klassId}")
List<Student> getAllByKlassId(Long klassId);
}
I’ve been learning for a whole night. Although I haven’t learned the advanced features like L2 cache, I’m still learningMyBatis
It can be regarded as another general understanding.
Business is the number one, and all technologies serve the business. Programmers should pay attention to business and practical problems. I don’t like to write themSQL
Of course,SQL
Should beDBA
Go to professional study and optimize,MyBatis
It looks more like givingDBA
The same frame is used.
Fully automated ORM
When a system is designed, the rest of the work is to move bricks.
Of course, the simpler the brick is, the better it isSQL
,Hibernate
Walk up.
public interface TeacherRepository extends CrudRepository<Teacher, Long> {
}
It’s completely object-based and more business focused.
How to choose?
Many people are “you see Alipay.”MyBatis
I’ll use it, tooMyBatis
”。
This isStackOverflow
The last ten years ago about the comparison of the two topics: https://stackoverflow.com/questions/1984548/hibernate-vs-ibatis
The final results are as follows:
iBatis
andHibernate
It’s a completely different thing(iBatis
yesMyBatis
The predecessor of.
If you’re object centric, thenHibernate
Better; if it’s database centric, theniBatis
Better.
If you design a system architecture that doesn’t require high concurrency,Hibernate
Most appropriately, the object model makes the code very concise, but at a high cost.
If you take over a legacy database and need to write complexSQL
Inquiry, thatiBatis
More appropriate.
To sum up, performance issues are:Hibernate
Convenient, but there will be performance loss;MyBatis
It has performance advantages.
summary
All saidMyBatis
It is suitable for high concurrency, but what about high concurrencyMyBatis
Can we cover it?
Business is the boss. If we really encounter high concurrency requirements, it is time for us to improve.