Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can Mybatis support mapping the dynamic columns to an map field of a bean?

Tags:

java

sql

mybatis

I have a requirement which may be little complicated. Think about I have bean class like:

public class A {
   private String column1;
   private String column2;
   private Map<String,String> dynamicColumns = Maps.newHashMap();
   ....
   getter&setter of column1 and column2
   ....
   public void addExtraColumnValue(String column, String value) {
     dynamicColumns.put(column, value);
   }

}

The dynamicColumns is determined by the mapper sql like this:

<select id="queryDynamicColumns" parameterType="java.util.Map"
    resultMap="aResultMap">
         select colum1,colum2, ${dynamicColumns} from table_1
</select>

How do I write this resultMap?

I wonder do the mybatis can support this mapping in mapper configuration?( the dynamic columns value will put into the map. ) I do not get a good answer from the official website, and also I try the plugin which intercept the resultSetHandler and it seems it do not give a help for my case by looking the source code of DefaultResultSetHandler.

like image 291
truejasonxiefans Avatar asked May 10 '16 10:05

truejasonxiefans


People also ask

What is MyBatis used for?

MyBatis is an open source persistence framework which simplifies the implementation of database access in Java applications. It provides the support for custom SQL, stored procedures and different types of mapping relations. Simply put, it's an alternative to JDBC and Hibernate.

What is resultMap in MyBatis?

The resultMap element is the most important and powerful element in MyBatis. It's what allows you to do away with 90% of the code that JDBC requires to retrieve data from ResultSet s, and in some cases allows you to do things that JDBC does not even support.


2 Answers

Have you tried ResultHandler?

question MyBatis - ResultHandler is not invoked could be useful.

In mybatis 3, you could see method SqlSession#select(String statement, ResultHandler handler).

You could do what ever you want in your custom ResultHandler.

Please let me know, if any problem.


It comes to my mind, if you derived from DefaultResultSetHandler and look at this:

public List<Object> handleResultSets(Statement stmt) throws SQLException {
  final List<Object> multipleResults = new ArrayList<Object>();

  int resultSetCount = 0;
  ResultSetWrapper rsw = getFirstResultSet(stmt);

  List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  int resultMapCount = resultMaps.size();
  validateResultMapsCount(rsw, resultMapCount);
  while (rsw != null && resultMapCount > resultSetCount) {
    ResultMap resultMap = resultMaps.get(resultSetCount);
    handleResultSet(rsw, resultMap, multipleResults, null);
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
  }

  while (rsw != null && resultSetCount < mappedStatement.getResulSets().length) {
    ResultMapping parentMapping = nextResultMaps.get(mappedStatement.getResulSets()[  resultSetCount]);
    if (parentMapping != null) {
      String nestedResultMapId = parentMapping.getNestedResultMapId();
      ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
      handleResultSet(rsw, resultMap, null, parentMapping);
    }
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
  }

  return collapseSingleResultList(multipleResults);
}

You can update the resultMaps runtime information, such as update its ResultMapping#column and then do dynamic binding. That's should work!

like image 114
Gemini Keith Avatar answered Oct 05 '22 14:10

Gemini Keith


Yes it can be done.

1.Whatever you are doing to select dynamic columns is ok.

2.To map the result: Since you are selecting the columns(dynamic) from table_1(Which will not change),you can have a POJO class with the fields present in table_1 and put that in resultMap.

<select id="queryDynamicColumns" parameterType="java.util.Map"
    resultMap="**Pojo Class With Fields As Columns of table_1**">
         select colum1,colum2, ${dynamicColumns} from table_1
</select>

Update:

If your database table columns changes than try using JAVA REFLECTION to dynamic columns

like image 25
Prasanna Kumar H A Avatar answered Oct 05 '22 15:10

Prasanna Kumar H A