preface
In the traditional SSM project, mybatis is the database connection framework commonly used in our development program, and we often ask about the implementation principle of mybayis in the interview. Therefore, we need to fully understand its underlying principle, and now we can preliminarily understand mysql through a custom framework.
Tip: the following is the main content of this article. The following cases can be used for reference
1, Implementation of native jdbc and its disadvantages and solutions?
Example: the native jdbc connection database code is as follows
public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // Load database driver Class.forName("com.mysql.jdbc.Driver"); // Get the database link through the driver management class connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis? characterEncoding=utf-8", "root", "root"); // Define sql statement? Represents a placeholder String sql = "select * from user where username = ?"; // Get preprocessing statement preparedStatement = connection.prepareStatement(sql); // Set the parameter. The first parameter is the sequence number of the parameter in the sql statement (starting from 1), and the second parameter is the set parameter value preparedStatement.setString(1, "tom"); // Send sql to the database to execute the query and query the result set resultSet = preparedStatement.executeQuery(); // Traverse the query result set while (resultSet.next()) { int id = resultSet.getInt("id"); String username = resultSet.getString("username"); // Encapsulate User user.setId(id); user.setUsername(username); } System.out.println(user); } } catch (Exception e) { e.printStackTrace(); } finally { } // Release resources if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { e.printStackTrace(); } } if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } if (connection != null) { try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } }
1. Disadvantages
The original jdbc development problems are as follows:
- The frequent creation and release of database connections cause a waste of system resources, which affects the system performance.
- SQL statements are hard coded in the code, which makes the code difficult to maintain. In practical application, SQL changes may be large, and SQL changes need to change the java code.
- There is hard coding in using preparedStatement to pass parameters to the possessive symbol, because the where conditions of sql statements are not necessarily, which may be more or less. Modifying sql also needs to modify the code, so the system is not easy to maintain.
- There is hard coding (query column name) for the result set parsing. The change of sql leads to the change of parsing code, which is difficult to maintain. It is more convenient to parse if the database records can be encapsulated into pojo objects
- There is a hard coding problem with the database connection information and driver.
2. Solutions
- Initialize connection resources using database connection pool
- Extract sql statements and database configuration information into xml configuration file
- Use reflection, introspection and other underlying technologies to automatically map the attributes and fields of entities and tables
II Customize a simple framework similar to mybatis
1. Implementation ideas
- First, put the sql and database configuration information into the xml configuration file to facilitate modification and management
- Using the object-oriented idea, the database Configuration information and sql of different tables are abstracted into objects, which are Configuration and MappedStatement respectively
- Use the class loader to read in the configuration file in the form of stream, parse it into custom objects and save it in memory.
- Use the factory mode SqlSessionFactoryBuilder build method to produce sqlsessionfactory. Sqlsessionfactory opens a SqlSession and interacts with the database through the default implementation class of the Executor.
- Parameter setting: use tag processing classes to replace placeholders and temporarily store parameter values in sql statements. PreparedStatement is used for sql precompiling. Finally, use reflection to obtain the incoming value and set it to PreparedStatement for submission and execution
- Reflection and introspection are used to encapsulate the returned results.
2. Partial code display
First, put the sql and database configuration information into the xml configuration file to facilitate modification and management
Database configuration file
<configuration> <!--Database configuration information--> <dataSource> <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/study"></property> <property name="username" value="root"></property> <property name="password" value="root"></property> </dataSource> <!--deposit mapper.xml Full path of--> <mapper resource="UserMapper.xml"></mapper> <!--deposit mapper.xml Full path of--> <mapper resource="ProductMapper.xml"></mapper> </configuration>
xml file
<mapper namespace = "com.my.dao.UserDao"> <!--Query data by criteria--> <select id="find" resultType="com.my.pojo.User" parameterType="com.my.pojo.User"> select * from user where id = #{id} and name = #{name} </select> <!--Query data by criteria--> <select id="findAll" resultType="com.my.pojo.User" parameterType="com.my.pojo.User"> select * from user </select> <!--Insert new data--> <insert id="save" resultType="int" parameterType="com.my.pojo.User"> insert into user (name,age) values( #{name},#{age}) </insert> <!--Modify data--> <update id="update" resultType="long" parameterType="com.my.pojo.User"> update user set age=#{age} where id = #{id} </update> <!--Delete data--> <delete id="delete" resultType="long" parameterType="com.my.pojo.User"> delete from user where id = #{id} </delete> </mapper>
**Configuration information parsing and encapsulation object – production DefaultSqlSessionFactory**
public SqlSessionFactory build(InputStream in) throws Exception { // First: use dom4j to parse the Configuration file and encapsulate the parsed content into Configuration XMLConfigBuilder xmlConfigBuilder = new XMLConfigBuilder(); Configuration configuration = xmlConfigBuilder.parseConfig(in); // Second: create sqlSessionFactory object: factory class: production sqlSession: session object DefaultSqlSessionFactory defaultSqlSessionFactory = new DefaultSqlSessionFactory(configuration); return defaultSqlSessionFactory; }
**DefaultSqlSessionFactory opens a DefaultSqlSession**
private Configuration configuration; public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; } @Override public SqlSession openSqlSession() { return new DefaultSqlSession(configuration); }
**DefaultSqlSession calls simpleexecution to perform specific operations**
private Configuration configuration; public DefaultSqlSession(Configuration configuration) { this.configuration = configuration; } public DefaultSqlSession() { } @Override public <E> List<E> find(String statementId, Object... params) throws Exception { SimpleExecutor simpleExecutor = new SimpleExecutor(); return simpleExecutor.find(configuration,configuration.getMappedStatementMap().get(statementId),params); } @Override public int update(String statementId, Object... params) throws Exception { SimpleExecutor simpleExecutor = new SimpleExecutor(); return simpleExecutor.update(configuration,configuration.getMappedStatementMap().get(statementId),params); } @Override public int save(String statementId, Object... params) throws Exception { SimpleExecutor simpleExecutor = new SimpleExecutor(); return simpleExecutor.save(configuration,configuration.getMappedStatementMap().get(statementId),params); } @Override public int delete(String statementId, Object... params) throws Exception { SimpleExecutor simpleExecutor = new SimpleExecutor(); return simpleExecutor.delete(configuration,configuration.getMappedStatementMap().get(statementId),params); }
Custom framework source code
summary
Here is only the preliminary implementation of mysql, which is not perfect. Please don't spray it. Subsequently, the implementation of mybatis is discussed through the source code.
In short, the general process is: first produce SqlSessionFactory through the build method of SqlSessionFactoryBuilderd, and use the factory mode to produce SqlSession. SqlSession calls the implementation class of Executor to execute specific methods.