Learn more about MyBatis return values and mybatis return values

Source: Internet
Author: User

Learn more about MyBatis return values and mybatis return values
Learn more about MyBatis return values

To learn about the returned values, we need to knowresultType,resultMapAnd the return value defined in the interface method.

Let's look at it first.resultTypeAndresultMap

ResultType and resultMap

Everyone should know that<select>There are two ways to set the return value for a tag:resultMapAndresultType.

ProcessingresultMapAndresultTypeThe Code is as follows:

private void setStatementResultMap(        String resultMap,        Class<?> resultType,        ResultSetType resultSetType,        MappedStatement.Builder statementBuilder) {    resultMap = applyCurrentNamespace(resultMap, true);    List<ResultMap> resultMaps = new ArrayList<ResultMap>();    if (resultMap != null) {        String[] resultMapNames = resultMap.split(",");        for (String resultMapName : resultMapNames) {            try {                resultMaps.add(configuration.getResultMap(resultMapName.trim()));            } catch (IllegalArgumentException e) {                throw new IncompleteElementException("Could not find result map " + resultMapName, e);            }        }    } else if (resultType != null) {        ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(                configuration,                statementBuilder.id() + "-Inline",                resultType,                new ArrayList<ResultMapping>(),                null);        resultMaps.add(inlineResultMapBuilder.build());    }    statementBuilder.resultMaps(resultMaps);    statementBuilder.resultSetType(resultSetType);}

We can see that priority is given here.resultMap,HoweverresultType.

Next, after MyBatis obtains data, if a row of results is processed (taking simple data as an example, nesting is not considered ):

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {    final ResultLoaderMap lazyLoader = new ResultLoaderMap();    Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);    if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {        final MetaObject metaObject = configuration.newMetaObject(resultObject);        boolean foundValues = resultMap.getConstructorResultMappings().size() > 0;        if (shouldApplyAutomaticMappings(resultMap, !AutoMappingBehavior.NONE.equals(configuration.getAutoMappingBehavior()))) {            foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;        }        foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;        foundValues = lazyLoader.size() > 0 || foundValues;        resultObject = foundValues ? resultObject : null;        return resultObject;    }    return resultObject;}

The important code in the above Code is as follows:

if (shouldApplyAutomaticMappings(resultMap, !AutoMappingBehavior.NONE.equals(configuration.getAutoMappingBehavior()))) {    foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;}foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;

If is used to determine whether or not it currently supportsAutomatic ing(Configurable). This is important ifNot Supported, So it cannot be used.resultTypeMethod, requiredresultMapMethod, ifSupported,resultTypeMethod andresultMapMethodCan be used at the same time.

The basic logic here isresultMapAutomatically map and assign values to attributesapplyAutomaticMappings.

If the object hasresultMap, Then proceedapplyPropertyMappingsMethod.

That is, first processingresultTypeFields automatically mapped inresultMapThe configuration field in,Both can be used at the same time!

The following two methods are described in order.

resultTypeMethod

If Automatic ing is supportedapplyAutomaticMappings, Which includesmetaObjectParameters.

final MetaObject metaObject = configuration.newMetaObject(resultObject);

Let's see how to createmetaObjectThe most important thing is thatReflectorClass:

for (String propName : readablePropertyNames) {    caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);}

Here, the attribute names in the object are mapped to the actual attribute names in uppercase. For exampleID:id.

InapplyAutomaticMappingsIn the first line, first obtain the column name without ing:

final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);

When obtaining the column Name:

for (String columnName : columnNames) {    final String upperColumnName = columnName.toUpperCase(Locale.ENGLISH);    if (mappedColumns.contains(upperColumnName)) {        mappedColumnNames.add(upperColumnName);    } else {        unmappedColumnNames.add(columnName);    }}

Note that the column name isConvert to uppercaseAnd savesmappedColumnNamesIng column andunmappedColumnNamesColumns not mapped.

Because both attribute names and query columns are in uppercase, the column name matches the attribute name as long as the column name is the same as the attribute name.

Therefore, when writing SQL statements, you do not need to convert the case sensitivity of the query column. automatic matching is case insensitive.

resultMapMethod

This method is also very simple, as mentioned abovemappedColumnNamesWhen determining whether a ing column is usedmappedColumns.contains(upperColumnName)To judge,mappedColumnsIs the ing column we configured,Do we have to write the configuration in uppercase?

Actually, this is not case sensitive.<result column="xxx" ../>OfcolumnIt is case insensitive. See the following code:

for (ResultMapping compositeResultMapping : resultMapping.getComposites()) {    final String compositeColumn = compositeResultMapping.getColumn();    if (compositeColumn != null) {        resultMap.mappedColumns.add(compositeColumn.toUpperCase(Locale.ENGLISH));    }}

It is also converted to uppercase.

Here we will discussresultTyptAndresultMapIt is over, but there is a simple question. Many people don't understand. What is it? Next title.

MyBatis interface Return Value

The interface return value is usually a result, orListAnd array.

How does MyBatis know if I want to return one or more results?

InMapperMethodPart of the Code in is as follows:

if (method.returnsVoid() && method.hasResultHandler()) {    executeWithResultHandler(sqlSession, args);    result = null;} else if (method.returnsMany()) {    result = executeForMany(sqlSession, args);} else if (method.returnsMap()) {    result = executeForMap(sqlSession, args);} else {    Object param = method.convertArgsToSqlCommandParam(args);    result = sqlSession.selectOne(command.getName(), param);}

The query result contains 4 conditions,void,list(Andarray),map,one.

Here it is important to determine the condition of if. This method is used to calculate the condition:

this.returnType = method.getReturnType();this.returnsVoid = void.class.equals(this.returnType);this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray());

We can see that these conditions are completely determined by the return value of the method. Therefore, if the returned value is an array or a set, multiple returned results are returned.

If there are multiple return values, but a POJO is written in the return value, what will happen if it is not a set or array?

The answer is: an error is reported.TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size()).

Whether one or more results are returned, MyBatis installs multiple results for query,selectOneIs to query one,selectListIs to query multiple, let's lookselectOneCode:

public <T> T selectOne(String statement, Object parameter) {    List<T> list = this.<T>selectList(statement, parameter);    if (list.size() == 1) {        return list.get(0);    } else if (list.size() > 1) {        throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());    } else {        return null;    }}

Note:

List<T> list = this.<T>selectList(statement, parameter);

In fact, no matter whether one or more results are queried, MyBatis queries by multiple results first. GetlistThe result is then judged.

If you query a resultlistA maximum of one return value is allowed. Through the code aboveif else if esleIt is understandable.

resultTyp,resultMapIs it related to the number of returned values?

It does not matter.

Pass the precedingresultTypeAndresultMapWe should know that this attribute is used to configure how JDBC query results are mapped to an object.

No matter what the return value is or how many values areresultTypeAndresultMapGenerate returned results.

The type of the returned result is determinedresultTypeAndresultMapDecide.

Type of the returned result

The type of the returned result is determinedresultTypeAndresultMapAre you surprised to decide ???

This is actually the case ..

For example, there is an entity.CountryAndCountry2.

InterfaceList<Country> selectAll(), In xml<select id="selectAll" resultType="Country2">.

What is the returned value when you call an interface? What you think is yoursListThe object type in isCountryBut they areCountry2

If the interface method isCountry selectById(Integer id), Which is<select id="selectById" resultType="Country2">, Because the types are inconsistent, an error is returned during query:java.lang.ClassCastException: xx.Country2 cannot be cast to xx.Country

Why?

This is because the interface call method is the encapsulation of the namespace call method..

What is the type of the returned result when you call it using the namespace method?

Is fromresultTypeAndresultMapThis is easy to understand. But I think it is different when I change to an interface.

This is because the interface method has more return values, so we will think that the returned value must be of this type. It is actually wrong.

Special Cases

When the pure annotation method is used, the return value type of the interface can be used.@ResultTypeThe annotation specifies the type of the return value, then the return value type written here will be usedresultType.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.