Home Java javaTutorial The processing flow of insert method, update method and delete method in java (Part 2)

The processing flow of insert method, update method and delete method in java (Part 2)

Jun 25, 2017 am 10:02 AM
insert mybatis analyze method Source code

Configuration’s newStatementHandler analysis

SimpleExecutor’s doUpdate method has been analyzed above:

 1 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { 2     Statement stmt = null; 3     try { 4       Configuration configuration = ms.getConfiguration(); 5       StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); 6       stmt = prepareStatement(handler, ms.getStatementLog()); 7       return handler.update(stmt); 8     } finally { 9       closeStatement(stmt);10     }11 }
Copy after login

When I re-read the newStatementHandler method in line 5 in the past two days, I found that the method analyzed above in this method is too simple. Let’s go through the newStatementHandler method of Configuration. The implementation of the method is:

1 public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {2     StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);3     statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);4     return statementHandler;5 }
Copy after login

The 3rd line of code is for adding a plug-in, which is nothing interesting. Take a look at the 2nd line of code. What is actually instantiated by the StatementHandler interface is RoutingStatementHandler, and the construction method The implementation is:

 1 public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 2  3     switch (ms.getStatementType()) { 4       case STATEMENT: 5         delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); 6         break; 7       case PREPARED: 8         delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); 9         break;10       case CALLABLE:11         delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);12         break;13       default:14         throw new ExecutorException("Unknown statement type: " + ms.getStatementType());15     }16 17 }
Copy after login

RoutingStatementHandler is also an implementation of the decorator pattern, which implements the StatementHandler interface and holds the StatementHandler interface reference delegate. The StatementType here is PREPARED, so the judgment on line 7 is executed to instantiate PreparedStatementHandler. The instantiation process is:

 1 protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 2     this.configuration = mappedStatement.getConfiguration(); 3     this.executor = executor; 4     this.mappedStatement = mappedStatement; 5     this.rowBounds = rowBounds; 6  7     this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 8     this.objectFactory = configuration.getObjectFactory(); 9 10     if (boundSql == null) { // issue #435, get the key before calculating the statement11       generateKeys(parameterObject);12       boundSql = mappedStatement.getBoundSql(parameterObject);13     }14 15     this.boundSql = boundSql;16 17     this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);18     this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);19 }
Copy after login

The focus here is BoundSql , which can be obtained through MappedStatement. Several important contents are stored in BoundSql:

  1. The parameter object itself

  2. Parameter list

  3. SQL statement to be executed

Some secondary development frameworks based on MyBatis usually get the SQL statements in BoundSql, modify them and reset them into BoundSql.

Generate Statement

##The process of generating Connection has been written above. This article continues Look, first let’s post the prepareStatement method of SimpleExecutor again:

1 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {2     Statement stmt;3     Connection connection = getConnection(statementLog);4     stmt = handler.prepare(connection, transaction.getTimeout());5     handler.parameterize(stmt);6     return stmt;7 }
Copy after login
Copy after login
Then there is the code in line 4, which generates Statement. The code in line 4 is implemented as:

  Statement prepare(Connection connection, Integer transactionTimeout)
Copy after login

delegate The above is the decorated role in the decorator mode. Its interface type is StatementHandler and its real type is PreparedStatementHandler. This has been analyzed at the beginning. Take a look at the prepare method implementation:

 1 public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException { 2     ErrorContext.instance().sql(boundSql.getSql()); 3     Statement statement = null; 4     try { 5       statement = instantiateStatement(connection); 6       setStatementTimeout(statement, transactionTimeout); 7       setFetchSize(statement); 8       return statement; 9     } catch (SQLException e) {10       closeStatement(statement);11       throw e;12     } catch (Exception e) {13       closeStatement(statement);14       throw new ExecutorException("Error preparing statement.  Cause: " + e, e);15     }16 }
Copy after login

The code in line 6 sets the query timeout, and the code in line 7 sets the received data size. I won’t follow up and look at it. Let’s look at the implementation of the instantiateStatement method in line 6:

 1 protected Statement instantiateStatement(Connection connection) throws SQLException { 2     String sql = boundSql.getSql(); 3     if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) { 4       String[] keyColumnNames = mappedStatement.getKeyColumns(); 5       if (keyColumnNames == null) { 6         return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); 7       } else { 8         return connection.prepareStatement(sql, keyColumnNames); 9       }10     } else if (mappedStatement.getResultSetType() != null) {11       return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);12     } else {13       return connection.prepareStatement(sql);14     }15 }
Copy after login

Line 2, get the real SQL statement from boundSql, The first part has already been analyzed. After getting the SQL statement, execute the judgment on lines 3 and 5. Here is the code we are familiar with to get the Statement through Connection. PreparedStatement is obtained through the prepareStatement method. Its true type is com.mysql.jdbc.JDBC4PreparedStatement, which is Subclass of PreparedStatement.

Statement parameter setting

After obtaining the Statement, the next step is to set the parameters. , look at the code for setting parameters, or go back to the prepareStatement method of SimpleExecutor:

1 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {2     Statement stmt;3     Connection connection = getConnection(statementLog);4     stmt = handler.prepare(connection, transaction.getTimeout());5     handler.parameterize(stmt);6     return stmt;7 }
Copy after login
Copy after login

and the code on line 5:

 1 public void parameterize(Statement statement) throws SQLException { 2     parameterHandler.setParameters((PreparedStatement) statement); 3 }
Copy after login

Continue with the code in line 2:

 1 public void setParameters(PreparedStatement ps) { 2     ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId()); 3     List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); 4     if (parameterMappings != null) { 5       for (int i = 0; i < parameterMappings.size(); i++) { 6         ParameterMapping parameterMapping = parameterMappings.get(i); 7         if (parameterMapping.getMode() != ParameterMode.OUT) { 8           Object value; 9           String propertyName = parameterMapping.getProperty();10           if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params11             value = boundSql.getAdditionalParameter(propertyName);12           } else if (parameterObject == null) {13             value = null;14           } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {15             value = parameterObject;16           } else {17             MetaObject metaObject = configuration.newMetaObject(parameterObject);18             value = metaObject.getValue(propertyName);19           }20           TypeHandler typeHandler = parameterMapping.getTypeHandler();21           JdbcType jdbcType = parameterMapping.getJdbcType();22           if (value == null && jdbcType == null) {23             jdbcType = configuration.getJdbcTypeForNull();24           }25           try {26             typeHandler.setParameter(ps, i + 1, value, jdbcType);27           } catch (TypeException e) {28             throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);29           } catch (SQLException e) {30             throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);31           }32         }33       }34     }35 }
Copy after login

最终执行的是第26行的代码,从26行的代码我们可以知道,参数设置到最后都是通过参数的TypeHandler来执行的,JDBC为我们预定义了很多TypeHandler,比如int值的TypeHandler就是IntegerTypeHandler,当然我们也可以定义自己的TypeHandler,通常来说继承BaseTypeHandler就可以了。

但是在此之前,会获取到Statement(setParameters方法形参)、占位符位置号(for循环的遍历参数i)、参数值(通过属性名获取)与jdbcType(配置在配置文件中,默认为null),最终执行TypeHandler的setParameters方法,这是BaseTypeHandler中的一个方法:

 1 public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException { 2     if (parameter == null) { 3       if (jdbcType == null) { 4         throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters."); 5       } 6       try { 7         ps.setNull(i, jdbcType.TYPE_CODE); 8       } catch (SQLException e) { 9         throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +10                 "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +11                 "Cause: " + e, e);12       }13     } else {14       try {15         setNonNullParameter(ps, i, parameter, jdbcType);16       } catch (Exception e) {17         throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " +18                 "Try setting a different JdbcType for this parameter or a different configuration property. " +19                 "Cause: " + e, e);20       }21     }22 }
Copy after login

这里的参数不为null,走13行的else,执行setNonNullParameter方法,这是IntegerTypeHandler中的一个方法:

   setNonNullParameter(PreparedStatement ps,
Copy after login

这里的代码就比较熟悉了,PreparedStatement的setInt方法。

执行更新操作并处理结果

最后一步,执行更新操作并对结果进行处理,回到SimpleExecuto的doUpdate方法:

 1 public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { 2     Statement stmt = null; 3     try { 4       Configuration configuration = ms.getConfiguration(); 5       StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); 6       stmt = prepareStatement(handler, ms.getStatementLog()); 7       return handler.update(stmt); 8     } finally { 9       closeStatement(stmt);10     }11 }
Copy after login

第6行已经准备好了Statement,第7行执行update操作并对结果进行处理并返回:

   update(Statement statement)
Copy after login

这里的委托delegate前面已经说过了,其真实类型是PreparedStatementHandler,update方法的实现为:

1 public int update(Statement statement) throws SQLException {2     PreparedStatement ps = (PreparedStatement) statement;3     ps.execute();4     int rows = ps.getUpdateCount();5     Object parameterObject = boundSql.getParameterObject();6     KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();7     keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);8     return rows;9 }
Copy after login

第3行的execute方法是PreparedStatement中的方法,execute方法执行操作,然后第4行通过getUpdateCount()方法获取本次操作更新了几条数据,作为最终的值返回给用户。

第5行的代码通过BoundSql获取参数对象,这里是MailDO对象,因为我们知道在插入场景下,开发者是有这种需求的,需要返回插入的主键id,此时会将主键id设置到MailDO中。

第6行的代码通过MappedStatement获取KeyGenerator,一个主键生成器。

第7行的代码做了一个操作完毕的后置处理:

<span style="color: #008080"> 1</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span><span style="color: #000000"> processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {</span><span style="color: #008080"> 2</span> <span style="color: #000000">    processBatch(ms, stmt, getParameters(parameter));</span><span style="color: #008080"> 3</span> <span style="color: #000000">}</span><span style="color: #008080"><br/></span>
Copy after login

首先将对象包装成集合类型,然后跟第2行的代码processBatch方法:

 1 public void processBatch(MappedStatement ms, Statement stmt, Collection<Object> parameters) { 2     ResultSet rs = null; 3     try { 4       rs = stmt.getGeneratedKeys(); 5       final Configuration configuration = ms.getConfiguration(); 6       final TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 7       final String[] keyProperties = ms.getKeyProperties(); 8       final ResultSetMetaData rsmd = rs.getMetaData(); 9       TypeHandler<?>[] typeHandlers = null;10       if (keyProperties != null && rsmd.getColumnCount() >= keyProperties.length) {11         for (Object parameter : parameters) {12           // there should be one row for each statement (also one for each parameter)13           if (!rs.next()) {14             break;15           }16           final MetaObject metaParam = configuration.newMetaObject(parameter);17           if (typeHandlers == null) {18             typeHandlers = getTypeHandlers(typeHandlerRegistry, metaParam, keyProperties, rsmd);19           }20           populateKeys(rs, metaParam, keyProperties, typeHandlers);21         }22       }23     } catch (Exception e) {24       throw new ExecutorException("Error getting generated key or setting result to parameter object. Cause: " + e, e);25     } finally {26       if (rs != null) {27         try {28           rs.close();29         } catch (Exception e) {30           // ignore31         }32       }33     }34 }
Copy after login

简单说这里就是遍历集合,通过JDBC4PreparedStatement的getGeneratedKeys获取ResultSet,然后从ResultSet中使用getLong方法获取生成的主键,设置到MailDO中。完成整个操作。

最后,本文演示的是insert数据的update方法流程,前文已经说过insert、update、delete在MyBatis中都是一样的,因此update、delete也是一样的操作,这里就不再赘述了。

The above is the detailed content of The processing flow of insert method, update method and delete method in java (Part 2). For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to write a novel in the Tomato Free Novel app. Share the tutorial on how to write a novel in Tomato Novel. How to write a novel in the Tomato Free Novel app. Share the tutorial on how to write a novel in Tomato Novel. Mar 28, 2024 pm 12:50 PM

Tomato Novel is a very popular novel reading software. We often have new novels and comics to read in Tomato Novel. Every novel and comic is very interesting. Many friends also want to write novels. Earn pocket money and edit the content of the novel you want to write into text. So how do we write the novel in it? My friends don’t know, so let’s go to this site together. Let’s take some time to look at an introduction to how to write a novel. Share the Tomato novel tutorial on how to write a novel. 1. First open the Tomato free novel app on your mobile phone and click on Personal Center - Writer Center. 2. Jump to the Tomato Writer Assistant page - click on Create a new book at the end of the novel.

How to enter bios on Colorful motherboard? Teach you two methods How to enter bios on Colorful motherboard? Teach you two methods Mar 13, 2024 pm 06:01 PM

Colorful motherboards enjoy high popularity and market share in the Chinese domestic market, but some users of Colorful motherboards still don’t know how to enter the bios for settings? In response to this situation, the editor has specially brought you two methods to enter the colorful motherboard bios. Come and try it! Method 1: Use the U disk startup shortcut key to directly enter the U disk installation system. The shortcut key for the Colorful motherboard to start the U disk with one click is ESC or F11. First, use Black Shark Installation Master to create a Black Shark U disk boot disk, and then turn on the computer. When you see the startup screen, continuously press the ESC or F11 key on the keyboard to enter a window for sequential selection of startup items. Move the cursor to the place where "USB" is displayed, and then

How to recover deleted contacts on WeChat (simple tutorial tells you how to recover deleted contacts) How to recover deleted contacts on WeChat (simple tutorial tells you how to recover deleted contacts) May 01, 2024 pm 12:01 PM

Unfortunately, people often delete certain contacts accidentally for some reasons. WeChat is a widely used social software. To help users solve this problem, this article will introduce how to retrieve deleted contacts in a simple way. 1. Understand the WeChat contact deletion mechanism. This provides us with the possibility to retrieve deleted contacts. The contact deletion mechanism in WeChat removes them from the address book, but does not delete them completely. 2. Use WeChat’s built-in “Contact Book Recovery” function. WeChat provides “Contact Book Recovery” to save time and energy. Users can quickly retrieve previously deleted contacts through this function. 3. Enter the WeChat settings page and click the lower right corner, open the WeChat application "Me" and click the settings icon in the upper right corner to enter the settings page.

Quickly master: How to open two WeChat accounts on Huawei mobile phones revealed! Quickly master: How to open two WeChat accounts on Huawei mobile phones revealed! Mar 23, 2024 am 10:42 AM

In today's society, mobile phones have become an indispensable part of our lives. As an important tool for our daily communication, work, and life, WeChat is often used. However, it may be necessary to separate two WeChat accounts when handling different transactions, which requires the mobile phone to support logging in to two WeChat accounts at the same time. As a well-known domestic brand, Huawei mobile phones are used by many people. So what is the method to open two WeChat accounts on Huawei mobile phones? Let’s reveal the secret of this method. First of all, you need to use two WeChat accounts at the same time on your Huawei mobile phone. The easiest way is to

The secret of hatching mobile dragon eggs is revealed (step by step to teach you how to successfully hatch mobile dragon eggs) The secret of hatching mobile dragon eggs is revealed (step by step to teach you how to successfully hatch mobile dragon eggs) May 04, 2024 pm 06:01 PM

Mobile games have become an integral part of people's lives with the development of technology. It has attracted the attention of many players with its cute dragon egg image and interesting hatching process, and one of the games that has attracted much attention is the mobile version of Dragon Egg. To help players better cultivate and grow their own dragons in the game, this article will introduce to you how to hatch dragon eggs in the mobile version. 1. Choose the appropriate type of dragon egg. Players need to carefully choose the type of dragon egg that they like and suit themselves, based on the different types of dragon egg attributes and abilities provided in the game. 2. Upgrade the level of the incubation machine. Players need to improve the level of the incubation machine by completing tasks and collecting props. The level of the incubation machine determines the hatching speed and hatching success rate. 3. Collect the resources required for hatching. Players need to be in the game

How to set font size on mobile phone (easily adjust font size on mobile phone) How to set font size on mobile phone (easily adjust font size on mobile phone) May 07, 2024 pm 03:34 PM

Setting font size has become an important personalization requirement as mobile phones become an important tool in people's daily lives. In order to meet the needs of different users, this article will introduce how to improve the mobile phone use experience and adjust the font size of the mobile phone through simple operations. Why do you need to adjust the font size of your mobile phone - Adjusting the font size can make the text clearer and easier to read - Suitable for the reading needs of users of different ages - Convenient for users with poor vision to use the font size setting function of the mobile phone system - How to enter the system settings interface - In Find and enter the "Display" option in the settings interface - find the "Font Size" option and adjust it. Adjust the font size with a third-party application - download and install an application that supports font size adjustment - open the application and enter the relevant settings interface - according to the individual

The difference between Go language methods and functions and analysis of application scenarios The difference between Go language methods and functions and analysis of application scenarios Apr 04, 2024 am 09:24 AM

The difference between Go language methods and functions lies in their association with structures: methods are associated with structures and are used to operate structure data or methods; functions are independent of types and are used to perform general operations.

How to choose a mobile phone screen protector to protect your mobile phone screen (several key points and tips for purchasing mobile phone screen protectors) How to choose a mobile phone screen protector to protect your mobile phone screen (several key points and tips for purchasing mobile phone screen protectors) May 07, 2024 pm 05:55 PM

Mobile phone film has become one of the indispensable accessories with the popularity of smartphones. To extend its service life, choose a suitable mobile phone film to protect the mobile phone screen. To help readers choose the most suitable mobile phone film for themselves, this article will introduce several key points and techniques for purchasing mobile phone film. Understand the materials and types of mobile phone films: PET film, TPU, etc. Mobile phone films are made of a variety of materials, including tempered glass. PET film is relatively soft, tempered glass film has good scratch resistance, and TPU has good shock-proof performance. It can be decided based on personal preference and needs when choosing. Consider the degree of screen protection. Different types of mobile phone films have different degrees of screen protection. PET film mainly plays an anti-scratch role, while tempered glass film has better drop resistance. You can choose to have better

See all articles