MyBatis multiple resultsets - mybatis

I am currently migrating code from iBatis 2 to MyBatis 3. I have a function that returns multiple results sets which we map to different classes. In iBatis we where able to map the different results using a comma separated list int the resultType like so:
<select id="findCashItems" parameterType="map" resultType="AdminCashBalance, AdminCashMovement, AdminCashTrx">
exec RequestActualAdministrativeData #{portfolioId}
</select>
But this does not appear to work in MyBatis 3. I can't find anything in the documentation except for a configuration item that, by default, enables multiple resultsets. But nothing on how to actually process them.

Using a resultMap with a comma separated list of result maps fixes this issue.
<resultMap id="adminCashBalance" type="AdminCashBalance">
...
</resultMap>
<resultMap id="adminCashMovement" type="AdminCashMovement">
...
</resultMap>
<resultMap id="adminCashTrx" type="AdminCashTrx">
...
</resultMap>
<select id="findCashItems" parameterType="map" resultMap="adminCashBalance, adminCashMovement, adminCashTrx">
exec RequestActualAdministrativeData #{portfolioId}
</select>

Related

resultMap in mybatis , I need to pass a List of Strings as return type. How to do this in the mapper file

<select id="getXXX" parameterType="java.util.List" resultMap="?">
</select>
In the above select query in my mapper file I need to get the resultMap as a List of Strings. How to implement as default Collection cannot be given directly.
I tried using a plain POJO class with a String variable or a List of String variable but it didnt work out.
If you need to get collection of Integers use the following for example:
<select id="getXXX" resultType="java.lang.Integer">
</select>
If you need to get collection of entities:
<select id="getXXX" resultType="com.domain.YourEntity">
</select>

How can I use <bind> within a loop while using MyBatis?

I wanted to build a sql like "(column like 'a%' or column like 'b%' or ...)" and a,b,etc. are elements in a collection.
So I came up with xml file like this
<foreach item="item" collection="items" open="(" separator=" or " close=")">
<bind name="pattern" value="item + '%'" />
column like #{pattern}
</foreach
But it didn't work out as I thought it would be.
The sql was like "(column like 'c%' or column like 'c%' or ...)" which c is the last element in the collection.
Now I use a CONCAT function to do the job.
column like CONCAT(#{pattern},'%')
Is there other good ways to do the job?
Thanks.
It is a known limitation i.e. <bind /> cannot be used inside <foreach /> and there is an open issue.
Using CONCAT is a good workaround for now.

mybatis <id> tag in <resultMap> behavior

I wrote mapping file like below.
<resultMap id="fooResultMap" type="Foo" >
<result column="NAME" property="name" jdbcType="VARCHAR" />
<association property="bar" resultMap="barResultMap" />
</resultMap>
When I get 2 record of same NAME colmun value, mybatis return only 1 Foo object.
I want 2 Foo object becouse bar's column is different.
So, I workaround below.
<resultMap id="fooResultMap" type="Foo" >
<id column="dummy_column_for_unique" />
<result column="NAME" property="name" jdbcType="VARCHAR" />
<association property="bar" resultMap="barResultMap" />
</resultMap>
I added <id> tag in <resultMap> and "dummy_column_for_unique" column is dummy(not exists).
I successfully got 2 Foo object.
I suppose dummy column result in null, and mybatis probably handle null value as different record.
But such behavior is not explained in manual or other resources on internet I searched.
Is there any information of this behavior ?
In mybatis's mailing list, I was recommended to use row number.
https://groups.google.com/forum/#!topic/mybatis-user/FAvrJ4piYlU
So, my final resultMap is like below.
<resultMap id="fooResultMap" type="Foo" >
<id column="rownum" />
<result column="NAME" property="name" jdbcType="VARCHAR" />
<association property="bar" resultMap="barResultMap" />
</resultMap>
And sql is like below(original sql is wraped by outer select sentence for not modifying original sql, and this sql grammar is for mysql).
select #rownum:=#rownum+1 as rownum, org.* from (
### original sql ###
) org, (select #rownum:=0) r
I hope this will help someone.
MyBatis maps the objects using the ID. If there is no ID in the ResultMap, they are all mapped in the same object.
Your table should have a primary key, but I guess that creating a fake ID as you did might serve as a workaround.

Populate a <SELECT> using custom tag?

My application needs to populate html selects with options from custom queries. I was trying to put the logic into a generic custom tag to do this so that my view is cleaner and more readable. I'm new to cfml.
Here is my code:
<!--- ```````````````````````````````````````````````````````````````````````````` --->
<!--- This tag will populate any SELECT with the OPTIONs pulled from the database. --->
<!--- The attributes of this tag are --->
<!--- data_source: The datasource for the query --->
<!--- table_source: The table used for the query --->
<!--- option_value_source: The DB cell to use for the value of the option. --->
<!--- option_inner_source: The DB cell to use for the value of the inner text. --->
<!--- ____________________________________________________________________________ --->
<cfquery name="option_query" datasource="#Attributes.data_source#">
SELECT * FROM #Attributes.table_source#
</cfquery>
<cfoutput query="option_query">
<option value="#Attributes.option_value_source#"> <!--- The cell to be used for the value of the option --->
#Attributes.option_inner_source# <!--- The cell to be used for the inner text of the option --->
</option>
</cfoutput>
I'm calling that with:
<label>
Class Name
<select name="className" id="className">
<cf_getOptions data_source="codify" table_source="classes" option_value_source="classes.id" option_inner_source="classes.name">
</select>
</label>
The result is that I get a SELECT populated with the word class.name for each result.
What is the most cfml way to do this (I assume people wouldn't normally use custom tags for this)? Is it possible to rewrite this code to get the correct result?
You're close (and good on you for using custom tags, btw).
You need to tell CF you want the column value from the query, not just the value of the passed-in attribute. So it'd be this:
<cfoutput query="option_query">
<option value="#option_query[Attributes.option_value_source][currentRow]#">
#option_query[Attributes.option_inner_source][currentRow]#
</option>
</cfoutput>
One can only use a direct reference to a column name the way you originally had, but you need an indirect reference here, which means the code gets a bit more cumbersome.

Spring MVC 3 - custom labels in <form:select>

I'm creating a form in which user will be able to choose (among the others) the factory of a product.
Each factory is identified by and ID and has specific address.
I want to use custom label in following code:
<form:select items="${factories}" path="factory" itemValue="id" itemLabel="..."/>
At first i tried using Spring Formatter functionality (org.springframework.format.Formatter interface), but when I did this, and when I removed "itemLabel" attribute to have it displayed automatically via Formatter):
<form:select items="${factories}" path="factory" itemValue="id"/>
But then It wasn't selecting proper value if it was set (in case of editing).
Then I tried to:
<form:select path="factory" itemValue="id">
<c:forEach ...>
<form:option value="${factory.id}" label="${factory.address.city} ${factory.address.street}"
</c:foreach>
</form:select>
But as in earlier solution spring was not selecting proper value that was set in model.
My question is:
Is it possible to format entity in a way, that form:select works properly, when a value of select field is not the same as its label.
I had the same problem, the trouble is the form:option value and label maps directly to a property rather than having the flexibility to specify jstl.
So you have to hand crank the html, to something like:
<select name="factory">
<c:forEach var="factory" items="${factories}" >
<option value="${factory.id}" label="${factory.address.city} ${factory.address.street}"/>
</c:forEach>
</select>
Spring will pick up the 'path' based on the name attribute('factory' in this case), as it will try and map to the model object you are using automatically.
Another way is to add another field to the model to concatenate and format label as you wish. And if its an #Entity object then make the field #Transient.
You can also override toString() method in Factory class
#Override
public String toString() {
return "desired string";
}
Then in your jsp
<form:select items="${factories}" itemValue="id" path="factory"/>