Get HashMap as Result for select - mybatis

Hi i want query database with myBatis and want return Map
I have daoInterface Like
public interface IDocDao extends IBasicDao {
public Map<Integer, Integer> getDocByA();
}
And mapper
<select id="getDocByA" resultMap="myHashMap">
SELECT b_id, count(1) AS count FROM table_a GROUP BY b_id
</select>
And need to return 1 map with all this values, not List of Maps
thx. Pavel

If you want to return a HashMap, you need to set it as a resultType, not as a resultMap. You don't need to define myHashMap, hashmap is enough.
<select id="getDocByA" resultType="hashmap">
SELECT b_id, count(1) AS count FROM table_a GROUP BY b_id
</select>

In your way, mybatis will return this:
[{b_id=b_id1, count=count1}, {b_id=b_id2, count=count2}]. So you need to define a list to receive this data, then you can convert it into a Map by additional code to loop the list.

Related

by use mybatis ,when the column name include dot notation, like this 'test.name' ,it will return nested Object,how to solve it?

his is my test sql:
<select id="getMap" resultType="java.util.LinkedHashMap">
select "test.name" from test where id = 1
</select>
java:
List<LinkedHashMap<String, String>> map = dataMapper.getMap();
log.info("{}", map);
output: [{test={name=628}}]
correct output should be: [{test.name=628}]
just like:mybatis autoMapping map and the column name has spot like this 'test.name' , the name will be split

Is it possible to return custom Java objects combining multiple aggregates in Spring Data JDBC?

I have multiple aggregate classes, such as Request, Scribe, Candidate, and Exam.
Sample schema:
Request (id, scribe_id, candidate_id, exam_id, status)
Scribe (id, name)
Candidate (id, name)
Exam (id, name, schedule)
As you can see, Request table has references to Scribe, Candidate, and Exam tables.
For one of the requirements, I need to return all requests based on a condition by including all the corresponding details of scribe, candidate, and exam.
For this, the query in my repository class will be similar to the following:
SELECT r.id, r.status, c.name, s.name,
e.schedule, e.name
FROM request r
JOIN candidate c ON r.candidate=c.id
JOIN scribe s ON r.scribe=s.id
JOIN exam e ON r.exam=e.id
WHERE <some-condition>
Now, is there a way to map the result of this query directly to a custom Java object and return the same in Spring Data JDBC?
I believe another alternative is to use the Spring JDBC template.
Curious, any out-of-the-box support from Spring Data JDBC?
Thanks.
I am able to return custom Java object by setting rowMapperClass value of org.springframework.data.jdbc.repository.query.Query annotation. For this need to define RowMapper for custom Java object.
Changes look similar to the following:
public class RequestResourceRowMapper implements RowMapper<RequestResource> {
#Override
public RequestResource mapRow(ResultSet resultSet, int rowNumber) throws SQLException { ... }
}
In repository class, need to set rowMapper value.
#Query(value = """
SELECT r.id, r.status, c.name, s.name,
e.schedule, e.name
FROM request r
JOIN candidate c ON r.candidate=c.id
JOIN scribe s ON r.scribe=s.id
JOIN exam e ON r.exam=e.id
WHERE <some-condition>
""",
rowMapperClass = RequestResourceRowMapper.class)
List<RequestResource> searchRequestResources(...);
This could have even been possible without using a custom row mapper as well, but in that case, you will have to assign different names to the columns across the tables. You could have defined a simple class and defined all the fields in there and for mapping the java fields with the corresponding columns in the table, you could have used the #Column attributes example:
public class RequestData {
#Column("id")
private Integer requestId;
#Column("scribe_id")
private String scribeId;
#Column("candidate_id")
private Integer candidateId;
#Column("scribe_name")
private String scribeName;
#Column("candidate_name")
private String candidateName;
#Column("exam_name")
private String examName;
#Column("exam_schedule")
private String examSchedule;
}
However, for such case, you need to have different column names across the schema's which might not be possible in your case as you have same column names in multiple schemas.

Laravel eloquent limit query

I have 3 tables TAble, TableB and TableC.
each one with 1 milion registers.
And i have the Laravel eloquent query.
$list= TableA::with([
'TableB',
'TableC'
])
->whereIn('field1',['A','B','C'])
->where('created_at','>=','2018-01-01') ->orderBy('fieldC', 'ASC')->orderBy('created_at', 'ASC')
->get()
->take(50) ;
TableA have TableB and TableC mapping this way.
public function TableB(){
return $this->belongsTo('TableB', 'fk_id', 'id');
}
public function TableC(){
return $this->hasMany('TableC');
}
How can i execute this query limiting number of registes in "TableB" and "TableC".
if i use take() it only limits the final result.
What do you want to do?
If you want to process data in chunks use
->chunk(50, function ($data) use ($variable) {
//process
});
If you want display data in tables with pages use paginate.

MyBatis - lists of primitive types

This seems to have eluded me. I know I can use a map to return a vanilla set of rows from a myBatis query but how to do it with a list of primitive types?
e.g. If I had SQL like:
select product_price from products
Does this require a resultMap? I've tried to use java.util.ArrayList as the result type but get class not found errors.
In a similar vein, how do I pass a list of items as an argument to a query.
Any input, pointers to docs appreciated.
Just declare the resultType as the primitive type that you want, which in your case is a Long. It will be returned as a list.
<select id="getPrice" resultType="java.lang.Long">
select product_price from products
</select>
In the mapper interface you should expect to get back a list of Long.
List<Long> getPrice();
Try using below code snippet inside your resultmap for product_price column mapping -
<collection property="price" ofType="java.lang.Long">
<result property="price" column="product_price"/>
</collection>
try using resultMap
<resultMap type="java.lang.Long" id="domainsResult">
<result property="" column="product_price"/>
</resultMap>
<select id="getPrice" resultMap="domainsResult">
select product_price from products
</select>
It will give you a List priceList.
Trey this :
You will get it as a list of map if you write like this:
<select id="getPrice" resultType="Hashmap">
select product_price from products
</select>
Where the key will be column name. Each map will contain a single entry. If You want an ArrayList then you can write a function to convert this map to an ArrayList:
public List listFromListOfMap (List<Map> listOfMap ) {
List<Integer> prices = new ArrayLisyt<Integer>();
for(int i = 0; i < listOfMap.size(); i++) {
Integer value = (Integer)listOfMap.get(i).get("product_price");
prices.add(value);
}
return prices;
}
Hope this helps :)

Is that possible to generate a list of maps from myBatis

for example, I have queries select id, name, age, address from staffs, instead of having a list of Staff object. I'd prefer to have a list of maps, as
list{
map{
("id", 123),
("name","jackie"),
("address", "canada"),
("age",26)
}
map{
("id", 126),
("name","james"),
("address", "canada"),
("age",27)
}
}
is that possible, and how to do that, if possible? Thanks.
Yes it is possible. You can set resultType as Hashmap in your mapper xml file, and it will return a list of maps.
<select id="selectFromStaffs" resultType="Hashmap">
select id, name, age, address from staffs
</select>
And you get it the same way:
...
List listOfMaps = sqlSession.selectList("selectFromStaffs");
...
You can read more about it in the User Guide.
In mapper xml type resultType as "map" or "Hashmap", mapper interface you must write reutrn type as a "List":
StaffMapper.xml
<select id="getStaffList" resultType="map">
select id, name, age, address from staffs
</select>
StaffMapper.java
import java.util.List;
import java.util.Map;
public interface StaffMapper {
List<Map<String, Object>> getStaffList();//List getStaffList();
}