In MyBatis, How to specify result type for a SelectProvider

12.8k Views Asked by At

This is my first post, using my poor English...

I am using MyBatis3.0

In a query, i used SqlBuilder with a method as following:

public class DataStatisticSqlBuilder extends SqlBuilder{ 

public String getDataQtyListSql(Map<String, Object> map){

and a mapper interface as following:

public interface DataStatisticMapper {

@SelectProvider(type=DataStatisticSqlBuilder.class, method="getDataQtyListSql")

public List<Map<String, Object>> getDataQtyList(@Param("groups")
List<DataStatisticSqlBuilder.Group> groups, @Param("quatity") Integer quatity, @Param("struct") Struct struct); 
}

When i called

session.getMapper(DataStatisticMapper.class).getDataQtyList(...some parameters)

i got the following result output in the console:

<==    Columns: PROJECT, PRJ_COUNT, TAR_COUNT, SITE_COUNT, PARAM_COUNT
<==        Row: project A, 1, 1, 0, 0 
<==        Row: project B, 1, 1, 0, 0

Based on the above output, the expected result should be a List [Map, Map, ...], but the actual result is [null, null]. Seems the result is not mapped to HashMap. How to set result type to HashMap on this query?

Maybe use some annotations, but i didn't find them.

Thanks very much.

1

There are 1 best solutions below

0
Migrus On

I got the same [null, null] trying to handle some dynamically generated sql. The mybatis manual mentions the SqlBuilder, but does not suggest how to use the sql. I think your problem could be fixed by adding a @Results and @Result annotation. That should work if the result columns are always the same, see for example at the end of @Results example

In my use I won't know which columns there are so here is what I eventually did.

In my mapper xml file:

  <update id="executeUpdate">
    ${stmt}
  </update>

  <select id="executeQuery" resultType="java.util.Map">
    ${stmt}
  </select>

${} instead of #{} will insert the string as-is and not treat it as a jdbc ? parameter. That is the key to this solution. In your case this would be the sql returned by the @SelectProvider and you would add a @Param("stmt") for passing the actual sql to run.

In the mybatis interface corresponding to the xml file:

void executeUpdate(DynamicSqlDao.ParameterObject po);
List<Map<String,Object>> executeQuery(DynamicSqlDao.ParameterObject po);

The ParameterObject is a simple bean:

@Data
public class ParameterObject
{
    String stmt;
    Map<String,Object> param;
}

(@Data is from Project Lombok and generates getter/setters)

I can now call my interface "dao" like this:

Map<String,Object> pmap = new HashMap<String,Object>();
pmap.put("apa", "banan");
ParameterObject po = new ParameterObject();
po.stmt = stmt;
po.param = pmap;
List<Map<String,Object>> result = dao.executeQuery(po);

ParameterObject could have been just a Map with a reserved name for the sql statement. Now that I've posted this, can someone else please post a more elegant solution ... :)