spring-data-couchbase error while finding all documents with PageRequest - java

Using Spring Data Couchbase I created a very simple repository
public interface UserDao extends PagingAndSortingRepository<User, String>
This should allow me to execute a paged findAll as follows:
Page<User> userResult = repo.findAll(new PageRequest(1, 20));
However the the following is always thrown:
Exception in thread "main" java.lang.IllegalStateException: Unknown query param: Page request [number: 1, size 20, sort: null]
at org.springframework.data.couchbase.repository.query.ViewBasedCouchbaseQuery.execute(ViewBasedCouchbaseQuery.java:47)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:337)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.couchbase.repository.support.ViewPostProcessor$ViewInterceptor.invoke(ViewPostProcessor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at $Proxy14.findAll(Unknown Source)
at com.polycom.cloudAxis.proxymanagement.model.Main.main(Main.java:41)
This doesn't happen if I create a Query and use the skip/limit/startKeyDocId, but would like to use PagingAndSortingRepository if possible.
Any idea what could be wrong? Thanks for all friendly help :)

i also had this same issue, here was the approach i took. its actually a very small change to the core implementation (which currently only support Query object types), essentially all I did was add another instance of check:
if (param instanceof Query) {
query = (Query) param;
} else if (param instanceof Pageable) {
pageable = (Pageable) param;
}
then added the logic for paging here, its been working so far but i havent fully vetted it so any comments from the community would be appreciated.
if (pageable != null) {
CouchbaseClient client = operations.getCouchbaseClient();
View view = client.getView(designDocName(), viewName());
// Paginator p = new Paginator(client, view, query,
// pageable.getPageSize());
Paginator paginator = client.paginatedQuery(view, query, pageable.getPageSize());
// now we need to goto the start point
ViewResponse viewResponse = null;
// views are 0 base
int i = 0;
while (paginator.hasNext()) {
viewResponse = paginator.next();
if (pageable.getPageNumber() == i++) {
LOGGER.debug("Found the response for this page: {} ", i);
break;
}
}
if (viewResponse == null) {
LOGGER.debug("no view response so leaving now");
return null;
}
Class<?> type = method.getEntityInformation().getJavaType();
final List result = new ArrayList(viewResponse.size());
for (final ViewRow row : viewResponse) {
result.add(operations.findById(row.getId(), type));
}
return result;
}
To get this wired up i had to do some things i didnt want to :D, i wanted to just override one method however to get to it required me to override many other things, so i ended up copying a little bit of code, ideally i would like to get this added as part of https://jira.spring.io/browse/DATACOUCH-93
And the whole impl here:
public class DCORepositoryFactory extends CouchbaseRepositoryFactory {
CouchbaseOperations couchbaseOperations;
MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext;
public DCORepositoryFactory(CouchbaseOperations couchbaseOperations) {
super(couchbaseOperations);
mappingContext = couchbaseOperations.getConverter().getMappingContext();
this.couchbaseOperations = couchbaseOperations;
}
#Override
protected Object getTargetRepository(RepositoryMetadata metadata) {
// TODO Auto-generated method stub
CouchbaseEntityInformation<?, Serializable> entityInformation = getEntityInformation(metadata.getDomainType());
final DCORepository simpleCouchbaseRepository = new DCORepository(entityInformation, couchbaseOperations);
simpleCouchbaseRepository.setViewMetadataProvider(ViewPostProcessor.INSTANCE.getViewMetadataProvider());
return simpleCouchbaseRepository;
}
#Override
protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key) {
return new CouchbaseQueryLookupStrategy();
}
/**
* Currently, only views are supported. N1QL support to be added.
*/
private class CouchbaseQueryLookupStrategy implements QueryLookupStrategy {
#Override
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method, metadata, mappingContext);
return new PagingViewBasedCouchbaseQuery(queryMethod, couchbaseOperations);
}
}
private static class PagingViewBasedCouchbaseQuery extends ViewBasedCouchbaseQuery {
private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory
.getLogger(DCORepositoryFactory.PagingViewBasedCouchbaseQuery.class);
private CouchbaseOperations operations;
private CouchbaseQueryMethod method;
public PagingViewBasedCouchbaseQuery(CouchbaseQueryMethod method, CouchbaseOperations operations) {
super(method, operations);
this.operations = operations;
this.method = method;
}
/*
* (non-Javadoc)
*
* #see org.springframework.data.couchbase.repository.query.
* ViewBasedCouchbaseQuery#execute(java.lang.Object[]) added the ability
* to support paging
*/
#Override
public Object execute(Object[] runtimeParams) {
Query query = null;
Pageable pageable = null;
for (Object param : runtimeParams) {
if (param instanceof Query) {
query = (Query) param;
} else if (param instanceof Pageable) {
pageable = (Pageable) param;
} else {
throw new IllegalStateException(
"Unknown query param: (btw null is also not allowed and pagable cannot be null) " + param);
}
}
if (query == null) {
query = new Query();
}
query.setReduce(false);
if (pageable != null) {
CouchbaseClient client = operations.getCouchbaseClient();
View view = client.getView(designDocName(), viewName());
// Paginator p = new Paginator(client, view, query,
// pageable.getPageSize());
Paginator paginator = client.paginatedQuery(view, query, pageable.getPageSize());
// now we need to goto the start point
ViewResponse viewResponse = null;
// views are 0 base
int i = 0;
while (paginator.hasNext()) {
viewResponse = paginator.next();
if (pageable.getPageNumber() == i++) {
LOGGER.debug("Found the response for this page: {} ", i);
break;
}
}
if (viewResponse == null) {
LOGGER.debug("no view response so leaving now");
return null;
}
Class<?> type = method.getEntityInformation().getJavaType();
final List result = new ArrayList(viewResponse.size());
for (final ViewRow row : viewResponse) {
result.add(operations.findById(row.getId(), type));
}
return result;
} else {
return operations.findByView(designDocName(), viewName(), query, method.getEntityInformation()
.getJavaType());
}
}
/**
* Returns the best-guess design document name.
*
* #return the design document name.
*/
private String designDocName() {
if (method.hasViewAnnotation()) {
return method.getViewAnnotation().designDocument();
} else {
return StringUtils.uncapitalize(method.getEntityInformation().getJavaType().getSimpleName());
}
}
/**
* Returns the best-guess view name.
*
* #return the view name.
*/
private String viewName() {
if (method.hasViewAnnotation()) {
return method.getViewAnnotation().viewName();
} else {
return StringUtils.uncapitalize(method.getName().replaceFirst("find", ""));
}
}
}
#Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata repositoryMetadata) {
return DCORepository.class;
}
}

Related

Repository Returning Null while attempting Horizontal Scaling of a Service Class

[ISSUE] repo always returns null when I call repo methods, while stepping through, throws null pointer exception. then front end receives
500: Http failure response for http://localhost:4200/api/aiprollout/updatecsv: 500 Internal Server Error
[HAVE TRIED] Adjusting AutoWired and components and service annotations.
[QUESTIONS]
1- Does every repo method need its own service and controller method?
2- Is it okay to create a new service that uses an existing controller?
3- If this new service uses SuperCsv and I create custom CsvCellProcessors, can these cell processors also call the repo? Should these cell processors perform logic? or should it be done else where? What class annotations should these cellProcessors classes have? #Component?
Any advice is greatly appreciated, feel a little lost at this point not even sure what to do.
[CODE]
Controller:
#RestController
#EnableConfigurationProperties({SpoofingConfigurationProperties.class})
#RequestMapping(value = "")
public class AipRolloutController {
private final Logger logger = some logger
private final AipRolloutService AipRolloutService;
private final CsvParserService csvParserService;
#Autowired
public AipRolloutController(AipRolloutService aipRolloutService, CsvParserService csvParserService) {
this.AipRolloutService = aipRolloutService;
this.csvParserService = csvParserService;
}
#PostMapping(value = "/updatecsv", produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<?> processCsv(#RequestParam("csvFile") MultipartFile csvFile) throws IOException {
if (csvFile.isEmpty()) return new ResponseEntity(
responceJson("please select a file!"),
HttpStatus.NO_CONTENT
);
csvParserService.parseCsvFile(csvFile);
return new ResponseEntity(
responceJson("Successfully uploaded - " + csvFile.getOriginalFilename()),
new HttpHeaders(),
HttpStatus.CREATED
);
}
Service:
#Service
public class AipRolloutService {
private static final Logger logger = some logger
#Autowired
private AIPRolloutRepository AIPRolloutRepository;
New Csv parser Service
#Service
public class CsvParserService {
#Autowired private AipRolloutService aipRolloutService;
public CsvParserService(AipRolloutService aipRolloutService) {
this.aipRolloutService = aipRolloutService;
}
public void parseCsvFile(MultipartFile csvFile) throws IOException {
CsvMapReader csvMapReader = new CsvMapReader(new InputStreamReader(csvFile.getInputStream()), CsvPreference.STANDARD_PREFERENCE);
parseCsv(csvMapReader);
csvMapReader.close();
}
private void parseCsv(CsvMapReader csvMapReader) throws IOException {
String[] header = csvMapReader.getHeader(true);
List<String> headers = Arrays.asList(header);
verifySourceColumn(headers);
verifyPovColumn(headers);
final CellProcessor[] processors = getProcessors(headers);
Map<String, Object> csvImportMap = null;
while ((csvImportMap = csvMapReader.read(header, processors)) != null) {
CsvImportDTO csvImportDto = new CsvImportDTO(csvImportMap);
if ( activationTypeP(csvImportDto) ){
int mssValue = Integer.parseInt(csvImportDto.getMssValue());
aipRolloutService.updateAipRollout(csvImportDto.getSource(),
csvImportDto.getPov(),
csvImportDto.getActivationType(),
mssValue);
}
}
}
private CellProcessor[] getProcessors(List<String> headers) {
CellProcessor[] processors = new CellProcessor[headers.size()];
int index = 0;
for (String header : headers) {
if (header.contains(SOURCE_ID)) {
processors[index++] = new CsvSourceIdCellParser();
} else if (header.contains(POV)) {
processors[index++] = new CsvPovCellParser();
} else if (header.contains(ACTIVATION_TYPE)) {
processors[index++] = new CsvActivationTypeCellParser();
} else if (header.contains(ACTIVATION_DATE)) {
processors[index++] = new Optional();
} else if (header.contains(DEACTIVATION_DATE)) {
processors[index++] = new Optional();
} else if (header.contains(MSS_VALUE)) {
processors[index++] = new CsvMssValueCellParser();
} else {
processors[index++] = null; // throw exception? wrong header info instead of allowing null?
}
}
return processors;
}
Custom Cell Processor that calls repo and returns null
public class CsvSourceIdCellParser extends CellProcessorAdaptor {
#Autowired AIPRolloutRepository aipRolloutRepository;
public CsvSourceIdCellParser(){ super(); }
// this constructor allows other processors to be chained
public CsvSourceIdCellParser(CellProcessor next){ super(next); }
#Override
public Object execute(Object value, CsvContext csvContext) {
// throws an Exception if the input is null
validateInputNotNull(value, csvContext);
// get rid of description only need first 3 #'s
value = value.toString().substring(0,3);
// check if WH exists
if( aipRolloutRepository.dcExistsInDatabase(value.toString()) )
return value;
else
throw new RuntimeException("Check Warehouse Value, Value Not Found "
+ "Row number: " + csvContext.getRowNumber()
+ " Column number: " + csvContext.getColumnNumber());
}
}
Repository
#Repository
public class AIPRolloutRepository {
private static final Logger logger = LoggerFactory.getLogger(AIPRolloutRepository.class);
#Autowired
JdbcTemplate jdbcTemplate;
public AIPRolloutRepository() {
}
public boolean dcExistsInDatabase(String dc){
// Query for a count saves time and memory, query for distinct saves time and memory on execution
boolean hasRecord =
jdbcTemplate
.query( "select count (distinct '" + dc +"')" +
"from xxcus.XX_AIP_ROLLOUT" +
"where DC = '" + dc + "';",
new Object[] { dc },
(ResultSet rs) -> {
if (rs.next()) {
return true;
}
return false;
}
);
return hasRecord;
}

what is this following error about in spring rest webservice api?

I'am creating a restapi , i am using java spring and i'am getting the following error.
Error:
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
My daoImpl class
#Override
public String getLoginDetails(VendorLogin vendorlogin) {
String getVendorData = "select vendor_ID from vendor_login where vendor_ID= ?
and password=?";
String name =null;
try{
name = (String) jdbcTemplate.queryForObject(getVendorData,new Object[]{
vendorlogin.getVendorLoginId(), vendorlogin.getPassWord()}, String.class);
}catch(Exception e){
e.printStackTrace();
}
return name;
}
my controller
#RequestMapping(value = Constants.REQ_MAP_LOGIN,
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
public String vendorloginMethodPost(#RequestBody VendorLogin vendoridlogin) {
String message = Constants.EMPTY_STRING;
String id = dao.getLoginDetails(vendoridlogin);
String password = dao.getLoginDetails(vendoridlogin);
if (id == null && password==null) {
message = "login FAIL";
}else{
message =" login Successfully";
}
return message;
}
SOLUTION
#Override
public String getLoginDetails(VendorLogin vendorlogin) {
String getVendorData = "select vendor_ID from vendor_login where vendor_ID= ? and password=?";
try {
name = (String) jdbcTemplate.queryForObject(
getVendorData,
new Object[]{vendorlogin.getVendorLoginId(), vendorlogin.getPassWord()},
new RowMapper<YourVendorObject>() {
public UserAttempts mapRow(ResultSet rs, int rowNum) throws SQLException {
// we suppose that your vendor_ID is String in DB
String vendor_ID = rs.getString("vendor_ID");
// if you wanna return the whole object use setters and getters
// from rs.getInt ... rs.getString ...
return vendor_ID;
}
});
return name;
} catch (EmptyResultDataAccessException e) {
return null;
}
}
public class EmptyResultDataAccessException extends IncorrectResultSizeDataAccessException
Data access exception thrown when a result was expected to have at least one row (or element) but zero rows (or elements) were actually returned.
The problem is, Spring throws an EmptyResultDataAccessException, instead of returning a null when record not found :
JdbcTemplate .java
package org.springframework.jdbc.core;
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
//...
public <T> T queryForObject(String sql, Object[] args,
RowMapper<T> rowMapper) throws DataAccessException {
List<T> results = query(sql, args, new RowMapperResultSetExtractor<T>(rowMapper, 1));
return DataAccessUtils.requiredSingleResult(results);
}
DataAccessUtils.java
package org.springframework.dao.support;
public abstract class DataAccessUtils {
//...
public static <T> T requiredSingleResult(Collection<T> results)
throws IncorrectResultSizeDataAccessException {
int size = (results != null ? results.size() : 0);
if (size == 0) {
throw new EmptyResultDataAccessException(1);
}
if (results.size() > 1) {
throw new IncorrectResultSizeDataAccessException(1, size);
}
return results.iterator().next();
}
check it here : source
try {
String getVendorData = "select vendor_ID from vendor_login where vendor_ID= ? and password=?";
String name =null;
name = (String) jdbcTemplate.queryForObject(getVendorData,new Object[]{vendorlogin.getVendorLoginId(), vendorlogin.getPassWord()}, String.class);
} catch (EmptyResultDataAccessException e) {
return null;
}

Hibernate gives a strange ClassCast exception (using Transformers)

This code:
#Override
public List<FactCodeDto> getAllFactsWithoutParentsAsFactDto() {
String completeQuery = FactCodeQueries.SELECT_DTO_FROM_FACT_WITH_NO_PARENTS;
Query query = createHibernateQueryForUnmappedTypeFactDto(completeQuery);
List<FactCodeDto> factDtoList = query.list(); //line 133
return factDtoList;
}
calling this method:
private Query createHibernateQueryForUnmappedTypeFactDto(String sqlQuery) throws HibernateException {
return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(Transformers.aliasToBean(FactCodeDto.class));
}
gives me a ClassCastException -> part of the trace:
Caused by: java.lang.ClassCastException: org.bamboomy.cjr.dto.FactCodeDto cannot be cast to java.util.Map
at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102)
at org.hibernate.transform.AliasToBeanResultTransformer.transformTuple(AliasToBeanResultTransformer.java:78)
at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:75)
at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:435)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423)
at org.hibernate.loader.Loader.list(Loader.java:2418)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:336)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1898)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:318)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125)
at org.bamboomy.cjr.dao.factcode.FactCodeDAOImpl.getAllFactsWithoutParentsAsFactDto(FactCodeDAOImpl.java:133)
Which is pretty strange because, indeed, if you look up the source code of Hibernate it tries to do this:
#Override
#SuppressWarnings("unchecked")
public void set(Object target, Object value, SessionFactoryImplementor factory) {
( (Map) target ).put( propertyName, value ); //line 102
}
Which doesn't make any sense...
target is of type Class and this code tries to cast it to Map,
why does it try to do that???
any pointers are more than welcome...
I'm using Hibernate 5 (and am upgrading from 3)...
edit: I also use Spring (4.2.1.RELEASE; also upgrading) which calls these methods upon deploy, any debugging pointers are most welcome as well...
edit 2: (the whole FactCodeDto class, as requested)
package org.bamboomy.cjr.dto;
import org.bamboomy.cjr.model.FactCode;
import org.bamboomy.cjr.model.FactCodeType;
import org.bamboomy.cjr.utility.FullDateUtil;
import org.bamboomy.cjr.utility.Locales;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.util.Assert;
import java.util.*;
#Getter
#Setter
#ToString
public class FactCodeDto extends TreeNodeValue {
private String cdFact;
private String cdFactSuffix;
private Boolean isSupplementCode;
private Boolean isTitleCode;
private Boolean mustBeFollowed;
private Date activeFrom;
private Date activeTo;
private Boolean isCode;
private Long idFact;
private Long idParent;
private String type;
Map<Locale, String> description = new HashMap<Locale, String>(3);
public FactCodeDto() {
}
public FactCodeDto(String prefix, String suffix) {
super();
this.cdFact = prefix;
this.cdFactSuffix = suffix;
}
public FactCodeDto(String cdFact, String cdFactSuffix, Boolean isSupplementCode, Boolean mustBeFollowed) {
super();
this.cdFact = cdFact;
this.cdFactSuffix = cdFactSuffix;
this.isSupplementCode = isSupplementCode;
this.mustBeFollowed = mustBeFollowed;
}
public FactCodeDto(String cdFact, String cdFactSuffix, Boolean isSupplementCode, Boolean mustBeFollowed, Long idFact, Long idParent, Boolean isCode, Boolean isTitleCode, Date from, Date to, Map<Locale, String> descriptions,String type) {
super();
this.cdFact = cdFact;
this.cdFactSuffix = cdFactSuffix;
this.isSupplementCode = isSupplementCode;
this.mustBeFollowed = mustBeFollowed;
this.idFact = idFact;
this.idParent = idParent;
this.isCode = isCode;
this.isTitleCode = isTitleCode;
this.activeFrom = from;
this.activeTo = to;
if (descriptions != null) {
this.description = descriptions;
}
this.type = type;
}
public FactCodeDto(FactCode fc) {
this(fc.getPrefix(), fc.getSuffix(), fc.isSupplementCode(), fc.isHasMandatorySupplCodes(), fc.getId(), fc.getParent(), fc.isActualCode(), fc.isTitleCode(), fc.getActiveFrom(), fc.getActiveTo(), fc.getAllDesc(),fc.getType().getCode());
}
public String formatCode() {
return FactCode.formatCode(cdFact, cdFactSuffix);
}
public boolean isActive() {
Date now = new Date(System.currentTimeMillis());
return FullDateUtil.isBetweenDates(now, this.activeFrom, this.activeTo);
}
public void setDescFr(String s) {
description.put(Locales.FRENCH, s);
}
public void setDescNl(String s) {
description.put(Locales.DUTCH, s);
}
public void setDescDe(String s) {
description.put(Locales.GERMAN, s);
}
/**
* public String toString() {
* StringBuilder sb = new StringBuilder();
* sb.append(getIdFact() + ": ")
* .append(getIdParent() + ": ")
* .append(" " + cdFact + cdFactSuffix + ": " + (isSupplementCode ? "NO Principal " : " Principal "))
* .append((mustBeFollowed ? " Must Be Followed " : "NOT Must Be Followed "));
* return sb.toString();
* }
*/
public Map<Locale, String> getDescription() {
return description;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
String fullCode = formatCode();
result = prime * result + ((fullCode == null) ? 0 : fullCode.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
FactCodeDto other = (FactCodeDto) obj;
return formatCode().equals(other.formatCode());
}
#Override
public boolean isChildOf(TreeNodeValue value) {
Assert.notNull(value);
boolean isChild = false;
if (value instanceof FactCodeDto) {
if (this.getIdParent() != null) {
isChild = this.getIdParent().equals(((FactCodeDto) value).getIdFact());
}
}
return isChild;
}
#Override
public boolean isBrotherOf(TreeNodeValue value) {
Assert.notNull(value);
boolean isBrother = false;
if (value instanceof FactCodeDto) {
if (this.getIdParent() != null) {
isBrother = this.getIdParent().equals(((FactCodeDto) value).getIdParent());
}
}
return isBrother;
}
#Override
public boolean isParentOf(TreeNodeValue value) {
Assert.notNull(value);
boolean isParent = false;
if (value instanceof FactCodeDto) {
isParent = this.getIdFact().equals(((FactCodeDto) value).getIdParent());
}
return isParent;
}
#Override
public int compareTo(TreeNodeValue to) {
if (to instanceof FactCodeDto) {
return formatCode().compareTo(((FactCodeDto) to).formatCode());
} else return 1;
}
public String getCode() {
return formatCode();
}
}
I found that AliasToBean has changed in Hibernate 5. For me adding getter for my field fixed the problem.
This exception occurs when the setters and getters are not mapped correctly to the column names.
Make sure you have the correct getters and setters for the query(Correct names and correct datatypes).
Read more about it here:
http://javahonk.com/java-lang-classcastexception-com-wfs-otc-datamodels-imagineexpirymodel-cannot-cast-java-util-map/
I do some investigation on this question. The problem is that Hibernate converts aliases for column names to upper case — cdFact becomesCDFACT.
Read for a more deeply explanation and workaround here:
mapping Hibernate query results to custom class?
In the end it wasn't so hard to find a solution,
I just created my own (custom) ResultTransformer and specified that in the setResultTransformer method:
private Query createHibernateQueryForUnmappedTypeFactDto(String sqlQuery) throws HibernateException {
return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(new FactCodeDtoResultTransformer());
//return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(Transformers.aliasToBean(FactCodeDto.class));
}
the code of the custom result transformer:
package org.bamboomy.cjr.dao.factcode;
import org.bamboomy.cjr.dto.FactCodeDto;
import java.util.Date;
import java.util.List;
/**
* Created by a162299 on 3-11-2015.
*/
public class FactCodeDtoResultTransformer implements org.hibernate.transform.ResultTransformer {
#Override
public Object transformTuple(Object[] objects, String[] strings) {
FactCodeDto result = new FactCodeDto();
for (int i = 0; i < objects.length; i++) {
setField(result, strings[i], objects[i]);
}
return result;
}
private void setField(FactCodeDto result, String string, Object object) {
if (string.equalsIgnoreCase("cdFact")) {
result.setCdFact((String) object);
} else if (string.equalsIgnoreCase("cdFactSuffix")) {
result.setCdFactSuffix((String) object);
} else if (string.equalsIgnoreCase("isSupplementCode")) {
result.setIsSupplementCode((Boolean) object);
} else if (string.equalsIgnoreCase("isTitleCode")) {
result.setIsTitleCode((Boolean) object);
} else if (string.equalsIgnoreCase("mustBeFollowed")) {
result.setMustBeFollowed((Boolean) object);
} else if (string.equalsIgnoreCase("activeFrom")) {
result.setActiveFrom((Date) object);
} else if (string.equalsIgnoreCase("activeTo")) {
result.setActiveTo((Date) object);
} else if (string.equalsIgnoreCase("descFr")) {
result.setDescFr((String) object);
} else if (string.equalsIgnoreCase("descNl")) {
result.setDescNl((String) object);
} else if (string.equalsIgnoreCase("descDe")) {
result.setDescDe((String) object);
} else if (string.equalsIgnoreCase("type")) {
result.setType((String) object);
} else if (string.equalsIgnoreCase("idFact")) {
result.setIdFact((Long) object);
} else if (string.equalsIgnoreCase("idParent")) {
result.setIdParent((Long) object);
} else if (string.equalsIgnoreCase("isCode")) {
result.setIsCode((Boolean) object);
} else {
throw new RuntimeException("unknown field");
}
}
#Override
public List transformList(List list) {
return list;
}
}
in hibernate 3 you could set Aliasses to queries but you can't do that anymore in hibernate 5 (correct me if I'm wrong) hence the aliasToBean is something you only can use when actually using aliasses; which I didn't, hence the exception.
Im my case :
=> write sql query and try to map result to Class List
=> Use "Transformers.aliasToBean"
=> get Error "cannot be cast to java.util.Map"
Solution :
=> just put \" before and after query aliases
ex:
"select first_name as \"firstName\" from test"
The problem is that Hibernate converts aliases for column names to upper case or lower case
I solved it by defining my own custom transformer as given below -
import org.hibernate.transform.BasicTransformerAdapter;
public class FluentHibernateResultTransformer extends BasicTransformerAdapter {
private static final long serialVersionUID = 6825154815776629666L;
private final Class<?> resultClass;
private NestedSetter[] setters;
public FluentHibernateResultTransformer(Class<?> resultClass) {
this.resultClass = resultClass;
}
#Override
public Object transformTuple(Object[] tuple, String[] aliases) {
createCachedSetters(resultClass, aliases);
Object result = ClassUtils.newInstance(resultClass);
for (int i = 0; i < aliases.length; i++) {
setters[i].set(result, tuple[i]);
}
return result;
}
private void createCachedSetters(Class<?> resultClass, String[] aliases) {
if (setters == null) {
setters = createSetters(resultClass, aliases);
}
}
private static NestedSetter[] createSetters(Class<?> resultClass, String[] aliases) {
NestedSetter[] result = new NestedSetter[aliases.length];
for (int i = 0; i < aliases.length; i++) {
result[i] = NestedSetter.create(resultClass, aliases[i]);
}
return result;
}
}
And used this way inside the repository method -
#Override
public List<WalletVO> getWalletRelatedData(WalletRequest walletRequest,
Set<String> requiredVariablesSet) throws GenericBusinessException {
String query = getWalletQuery(requiredVariablesSet);
try {
if (query != null && !query.isEmpty()) {
SQLQuery sqlQuery = mEntityManager.unwrap(Session.class).createSQLQuery(query);
return sqlQuery.setResultTransformer(new FluentHibernateResultTransformer(WalletVO.class))
.list();
}
} catch (Exception ex) {
exceptionThrower.throwDatabaseException(null, false);
}
return Collections.emptyList();
}
It worked perfectly !!!
Try putting Column names and field names both in capital letters.
This exception occurs when the class that you specified in the AliasToBeanResultTransformer does not have getter for the corresponding columns. Although the exception details from the hibernate are misleading.

How to intercept and change sql query dynamically in mybatis

I use mybatis to perform sql queries in my project. I need to intercept sql query before executing to apply some changed dynamically. I've read about #Interseptors like this:
#Intercepts({#Signature(type= Executor.class, method = "query", args = {...})})
public class ExamplePlugin implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
return invocation.proceed();
}
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public void setProperties(Properties properties) {
}
}
And it really intercepts executions, but there is no way to change sql query since appropriate field is not writable. Should I build new instance of whole object manually to just replace sql query? Where is the right place to intercept query execution to change it dynamically? Thank.
I hope it will help you:
#Intercepts( { #Signature(type = Executor.class, method = "query", args = {
MappedStatement.class, Object.class, RowBounds.class,
ResultHandler.class
})
})
public class SelectCountSqlInterceptor2 implements Interceptor
{
public static String COUNT = "_count";
private static int MAPPED_STATEMENT_INDEX = 0;
private static int PARAMETER_INDEX = 1;
#Override
public Object intercept(Invocation invocation) throws Throwable
{
processCountSql(invocation.getArgs());
return invocation.proceed();
}
#SuppressWarnings("rawtypes")
private void processCountSql(final Object[] queryArgs)
{
if (queryArgs[PARAMETER_INDEX] instanceof Map)
{
Map parameter = (Map) queryArgs[PARAMETER_INDEX];
if (parameter.containsKey(COUNT))
{
MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
BoundSql boundSql = ms.getBoundSql(parameter);
String sql = ms.getBoundSql(parameter).getSql().trim();
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),
getCountSQL(sql), boundSql.getParameterMappings(),
boundSql.getParameterObject());
MappedStatement newMs = copyFromMappedStatement(ms,
new OffsetLimitInterceptor.BoundSqlSqlSource(newBoundSql));
queryArgs[MAPPED_STATEMENT_INDEX] = newMs;
}
}
}
// see: MapperBuilderAssistant
#SuppressWarnings({ "unchecked", "rawtypes" })
private MappedStatement copyFromMappedStatement(MappedStatement ms,
SqlSource newSqlSource)
{
Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms
.getId(), newSqlSource, ms.getSqlCommandType());
builder.resource(ms.getResource());
builder.fetchSize(ms.getFetchSize());
builder.statementType(ms.getStatementType());
builder.keyGenerator(ms.getKeyGenerator());
// setStatementTimeout()
builder.timeout(ms.getTimeout());
// setParameterMap()
builder.parameterMap(ms.getParameterMap());
// setStatementResultMap()
List<ResultMap> resultMaps = new ArrayList<ResultMap>();
String id = "-inline";
if (ms.getResultMaps() != null)
{
id = ms.getResultMaps().get(0).getId() + "-inline";
}
ResultMap resultMap = new ResultMap.Builder(null, id, Long.class,
new ArrayList()).build();
resultMaps.add(resultMap);
builder.resultMaps(resultMaps);
builder.resultSetType(ms.getResultSetType());
// setStatementCache()
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
return builder.build();
}
private String getCountSQL(String sql)
{
String lowerCaseSQL = sql.toLowerCase().replace("\n", " ").replace("\t", " ");
int index = lowerCaseSQL.indexOf(" order ");
if (index != -1)
{
sql = sql.substring(0, index);
}
return "SELECT COUNT(*) from ( select 1 as col_c " + sql.substring(lowerCaseSQL.indexOf(" from ")) + " ) cnt";
}
#Override
public Object plugin(Object target)
{
return Plugin.wrap(target, this);
}
#Override
public void setProperties(Properties properties)
{
}
}
You may consider using a string template library (eg Velocity, Handlebars, Mustache) to help you
As of to date, there is even MyBatis-Velocity (http://mybatis.github.io/velocity-scripting/) to help you to do scripting for the sql.
Depending on the changes you want to make, you may want to use the dynamic sql feature of mybatis 3

ORMLite error no databasefield annotations exists

I have this error when I run my Android application:
No fields have a DatabaseField
annotation in class [[Lmodel.Vak;
My class Vak has annotations, so I really don't understand why it still giving me this error.
package model;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
#DatabaseTable(tableName = "vak")
public class Vak {
#DatabaseField(generatedId = true, columnName = "vakID", id=true) Long id;
#DatabaseField int rij;
#DatabaseField
int kolom;
...
}
I have a file called Databasehelper.java in which extends OrmLiteSqLiteOpenHelper and the file looks like this:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
// name of the database file for your application -- change to something
// appropriate for your app
private static final String DATABASE_NAME = "project56.db";
// any time you make changes to your database objects, you may have to
// increase the database version
private static final int DATABASE_VERSION = 1;
private DatabaseType databaseType = new SqliteAndroidDatabaseType();
// the DAO object we use to access the tables
private Dao<Vleugel, Long> vleugelDao = null;
private Dao<Verdieping, Long> verdiepingDao = null;
private Dao<NavigatiePunt, Long> navigatiePuntDao = null;
private Dao<Lokaal, Long> lokaalDao = null;
private Dao<Raster, Long> rasterDao = null;
private Dao<Vak, Long> vakDao = null;
private Dao<Graaf, Long> graafDao = null;
private Dao<Vertex, Long> vertexDao = null;
private Dao<Edge, Long> edgeDao = null;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
/**
* This is called when the database is first created. Usually you should
* call createTable statements here to create the tables that will store
* your data.
*/
#Override
public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
try {
Log.i(DatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource, Vleugel.class);
TableUtils.createTable(connectionSource, Verdieping.class);
TableUtils.createTable(connectionSource, NavigatiePunt.class);
TableUtils.createTable(connectionSource, Lokaal.class);
TableUtils.createTable(connectionSource, Raster.class);
TableUtils.createTable(connectionSource, Vak.class);
TableUtils.createTable(connectionSource, Graaf.class);
TableUtils.createTable(connectionSource, Vertex.class);
TableUtils.createTable(connectionSource, Edge.class);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
}
}
/**
* This is called when your application is upgraded and it has a higher
* version number. This allows you to adjust the various data to match the
* new version number.
*/
#Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource,
int oldVersion, int newVersion) {
try {
Log.i(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource, Vleugel.class, true);
TableUtils.dropTable(connectionSource, Verdieping.class, true);
TableUtils.dropTable(connectionSource, NavigatiePunt.class, true);
TableUtils.dropTable(connectionSource, Lokaal.class, true);
TableUtils.dropTable(connectionSource, Raster.class, true);
TableUtils.dropTable(connectionSource, Vak.class, true);
TableUtils.dropTable(connectionSource, Graaf.class, true);
TableUtils.dropTable(connectionSource, Vertex.class, true);
TableUtils.dropTable(connectionSource, Edge.class, true);
// after we drop the old databases, we create the new ones
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
/**
* Returns the Database Access Object (DAO) for the classes It will create
* it or just give the cached value.
*/
public Dao<Vleugel, Long> getVleugelDao() throws SQLException {
if (vleugelDao == null) {
vleugelDao = getDao(Vleugel.class);
}
return vleugelDao;
}
public Dao<Verdieping, Long> getVerdiepingDao() throws SQLException {
if (verdiepingDao == null) {
verdiepingDao = getDao(Verdieping.class);
}
return verdiepingDao;
}
public Dao<NavigatiePunt, Long> getNavigatiePuntDao() throws SQLException {
if (navigatiePuntDao == null) {
navigatiePuntDao = getDao(NavigatiePunt.class);
}
return navigatiePuntDao;
}
public Dao<Lokaal, Long> getLokaalDao() throws SQLException {
if (lokaalDao == null) {
lokaalDao = getDao(Lokaal.class);
}
return lokaalDao;
}
public Dao<Raster, Long> getRasterDao() throws SQLException {
if (rasterDao == null) {
rasterDao = getDao(Raster.class);
}
return rasterDao;
}
public Dao<Vak, Long> getVakDao() throws SQLException {
if (vakDao == null) {
vakDao = getDao(Vak.class);
}
return vakDao;
}
public Dao<Graaf, Long> getGraafDao() throws SQLException {
if (graafDao == null) {
graafDao = getDao(Graaf.class);
}
return graafDao;
}
public Dao<Vertex, Long> getVertexDao() throws SQLException {
if (vertexDao == null) {
vertexDao = getDao(Vertex.class);
}
return vertexDao;
}
public Dao<Edge, Long> getEdgeDao() throws SQLException {
if (edgeDao == null) {
edgeDao = getDao(Edge.class);
}
return edgeDao;
}
/**
* Close the database connections and clear any cached DAOs.
*/
#Override
public void close() {
super.close();
vleugelDao = null;
verdiepingDao = null;
navigatiePuntDao = null;
lokaalDao = null;
rasterDao = null;
vakDao = null;
graafDao = null;
vertexDao = null;
edgeDao = null;
}
}
I also have a file Controller which extends OrmLiteBaseActivity:
public class Controller extends OrmLiteBaseActivity<DatabaseHelper> {
Dao<Vleugel, Long> vleugelDao;
Dao<Verdieping, Long> verdiepingDao;
Dao<NavigatiePunt, Long> navigatiePuntDao;
Dao<Lokaal, Long> lokaalDao;
Dao<Raster, Long> rasterDao;
Dao<Graaf, Long> graafDao;
Dao<Vertex, Long> vertexDao;
Dao<Edge, Long> edgeDao;
Dao<Vak, Long> vakDao;
// Databasehelper is benodigd voor ORMLite
static {
OpenHelperManager.setOpenHelperFactory(new SqliteOpenHelperFactory() {
public OrmLiteSqliteOpenHelper getHelper(Context context) {
return new DatabaseHelper(context);
}
});
}
public Controller() throws SQLException {
/** initialiseren van dao */
vleugelDao = getHelper().getVleugelDao();
verdiepingDao = getHelper().getVerdiepingDao();
navigatiePuntDao = getHelper().getNavigatiePuntDao();
lokaalDao = getHelper().getLokaalDao();
rasterDao = getHelper().getRasterDao();
graafDao = getHelper().getGraafDao();
vertexDao = getHelper().getVertexDao();
edgeDao = getHelper().getEdgeDao();
vakDao = getHelper().getVakDao();
}
/**
* Haalt vleugel idNaam op uit dao object bijv. K1
*
* #return Vleugel
* #throws java.sql.SQLException
*/
public Vleugel getVleugel(String vleugelIDNaam)
throws java.sql.SQLException {
// select * from vleugel where idNaam='{vleugelIDNaam}'
QueryBuilder<Vleugel, Long> qb = vleugelDao.queryBuilder();
Where where = qb.where();
// the name field must be equal to "foo"
where.eq("idNaam", vleugelIDNaam);
PreparedQuery<Vleugel> preparedQuery = qb.prepare();
List<Vleugel> vleugelList = vleugelDao.query(preparedQuery);
Log.v("Getvleugel", vleugelList.size() + "");
if (vleugelList.size() == 1) {
return vleugelList.get(0);
}
return null;
}
public Verdieping getVerdieping(int nummer) throws java.sql.SQLException {
// TODO: Met querybuilder query naar db om verdieping te pakken
return null;
}
/**
* Haalt navigatiepunt op
*
* #param naam
* #return
* #throws java.sql.SQLException
*/
public NavigatiePunt getNavigatiePunt(String naam)
throws java.sql.SQLException {
// select * from navigatiepunt where naam='{naam}'
QueryBuilder<NavigatiePunt, Long> qb = navigatiePuntDao.queryBuilder();
Where where = qb.where();
where.eq("naam", naam);
PreparedQuery<NavigatiePunt> preparedQuery = qb.prepare();
List<NavigatiePunt> navigatieList = navigatiePuntDao
.query(preparedQuery);
Log.v("GetLokaal", navigatieList.size() + "");
if (navigatieList.size() == 1) {
return navigatieList.get(0);
}
return null;
}
/**
* Get lokaal object op basis van lokaalcode
*
* #param lokaalcode
* #return
* #throws java.sql.SQLException
*/
public Lokaal getLokaal(String lokaalcode) throws java.sql.SQLException {
// select * from lokaal where lokaalcode='{lokaalcode}'
QueryBuilder<Lokaal, Long> qb = lokaalDao.queryBuilder();
Where where = qb.where();
where.eq("lokaalcode", lokaalcode);
PreparedQuery<Lokaal> preparedQuery = qb.prepare();
List<Lokaal> lokaalList = lokaalDao.query(preparedQuery);
Log.v("GetLokaal", lokaalList.size() + "");
if (lokaalList.size() == 1) {
return lokaalList.get(0);
}
return null;
}
}
So do you have any advice on this, what should I check?
Could you check, are created table Vak in your DB? The absence of this table can be reason of this crash.
This turned out to be a bug in ORMLite around foreign object loops that was fixed in version 4.22. ORMLite was not properly handing the case where A has a foreign-field B which has a foreign-field to C which has a foreign-field back to A..
http://ormlite.com/releases/
Please send me some direct mail #Yanny if this does or doesn't work and I will tune this answer accordingly.
It's probably late for giving solution but this is my solution:
you see proguard try to obfuscating the code and if you read proguard in depth or intro
http://proguard.sourceforge.net/FAQ.html
what Shrinking in proguard -> Shrinking programs such as ProGuard can analyze bytecode and remove unused classes, fields, and methods.
so from this we can presume that it is removing your objects since it's not used by anywhere...
so wt you probably need?
you need to stop proguard from shirking that methods or objects from process
so this is the line for that..:
-keep class com.j256.**<br>
-keepclassmembers class com.j256.** { *; }<br>
-keep enum com.j256.**<br>
-keepclassmembers enum com.j256.** { *; }<br>
-keep interface com.j256.**<br>
-keepclassmembers interface com.j256.** { *; }
this line will keep proguard from removing my public methods and variables..
-keepclassmembers class classpath.** {
public *;
}
you need to write column name for atlest id... because it will search for it and will proguard change it's name... so you need to define column name id for primary key..

Categories