Im using Java 8 and Jdbi version 2.78 to query a database.
I have a table of key-value configurations for merchants.
I have a class which queries the database:
import com.clevergift.gson.MerchantConfigsBeanMapper;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
import java.util.Map;
public abstract class MerchantConfigDAO {
@Mapper(MerchantConfigsBeanMapper.class)
@SqlQuery("SELECT configKey, configValue FROM merchant_configs where merchant = :merchant")
public abstract Map<String, String> getMerchantConfigs(@Bind("merchant") String merchant);
}
And the MerchantConfigsBeanMapper
class should loop through the results:
import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class MerchantConfigsBeanMapper implements ResultSetMapper<Map<String, String>> {
@Override
public Map<String, String> map(int index, ResultSet r, StatementContext ctx) throws SQLException {
Map<String, String> configs = new HashMap<String, String>();
int rowcount = 0;
if (r.last()) {
rowcount = r.getRow();
r.beforeFirst(); // not rs.first() because the rs.next() below will move on, missing the first element
}
while (r.next()) {
configs.put(r.getString("configKey"), r.getString("configValue"));
}
return configs;
}
}
When I run this passing in "adidas", 3 results should obviously be returned. However, r
always only contains 1 result and r.getString("configValue")
is cbadmin
. r.last()
is always true as only 1 result is being returned.
How is this possible? Why doesn't r
contain all the results?
EDIT
I called the MerchantConfigDAO from the service:
import com.clevergift.services.MerchantConfigService;
import com.google.inject.Inject;
import java.util.Map;
public class MerchantConfigServiceImpl implements MerchantConfigService {
private MerchantConfigDAO merchantConfigDAO;
@Inject
public MerchantConfigServiceImpl(MerchantConfigDAO merchantConfigDAO) {
this.merchantConfigDAO = merchantConfigDAO;
}
public Map<String, String> getMerchantConfigs(String merchant) {
Map<String, String> merchantConfigs = this.merchantConfigDAO.getMerchantConfigs(merchant);
return merchantConfigs;
}
}
Even after implementing @ivans answer here, merchantConfigs
is still of length 1...
Mapper should map one row at a time with the following code. From documentation:
Row mappers are invoked once for each row in the result set.
@Override
public Map<String, String> map(int index, ResultSet r, StatementContext ctx) throws SQLException {
Map<String, String> configs = new HashMap<String, String>();
configs.put(r.getString("configKey"), r.getString("configValue"));
return configs;
}
If you still want to process whole ResultSet
in one call you nned to return List<Map<String, String>>
. One map
for each row in ResultSet
.
According to documentation
Query methods may return a single- or multi-row result, depending on whether the method return type looks like a collection.
Change your DAO method to return List<Map<String, String>>