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
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
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.
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.
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 :)
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();
}