spring data jpa dynamic query which has IN clause - spring

I want to create dynamic query in spring data jpa. Doing many search I can implement it, but I came across a problem when I add IN operator in where clause. I need to check id IN (longlist)
Here is my entity class
#Entity
#Table(name = "view_detail")
public class ViewDetailDom {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
#Column(name = "user_id")
private Long userId;
private String description;
Here is specification builder class and specification class
public class ViewDetailSpecificationsBuilder {
private final List<SearchCriteria> params;
public ViewDetailSpecificationsBuilder() {
params = new ArrayList<SearchCriteria>();
}
public ViewDetailSpecificationsBuilder with(String key, Operation operation, Object value) {
params.add(new SearchCriteria(key, operation, value));
return this;
}
public Specification<ViewDetailDom> build() {
if (params.size() == 0) {
return null;
}
List<Specification<ViewDetailDom>> specs = new ArrayList<Specification<ViewDetailDom>>();
for (SearchCriteria param : params) {
specs.add(new ViewDetailSpecification(param));
}
Specification<ViewDetailDom> result = specs.get(0);
for (int i = 1; i < specs.size(); i++) {
result = Specifications.where(result).and(specs.get(i));
}
return result;
}
}
public class ViewDetailSpecification implements Specification<ViewDetailDom> {
private SearchCriteria criteria = new SearchCriteria();
public ViewDetailSpecification(SearchCriteria searchCriteria) {
this.criteria.setKey(searchCriteria.getKey());
this.criteria.setOperation(searchCriteria.getOperation());
this.criteria.setValue(searchCriteria.getValue());
}
#Override
public Predicate toPredicate(Root<ViewDetailDom> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
String value = criteria.getValue().toString().replaceAll(" ", "%");
if (criteria.getOperation() != null && criteria.getOperation() != Operation.DEFAULT) {
if (criteria.getOperation() == Operation.GREATHERTHANEQUALTO) {
return builder.greaterThanOrEqualTo(root.<String>get(criteria.getKey()), value);
} else if (criteria.getOperation() == Operation.LESSTHANEQUALTO) {
return builder.lessThanOrEqualTo(root.<String>get(criteria.getKey()), value);
} else if (criteria.getOperation() == Operation.EQUAL) {
return builder.equal(root.<String>get(criteria.getKey()), value);
} else if (criteria.getOperation() == Operation.IN) {
Path<Long> view = root.<Long>get(criteria.getKey());
return view.in(criteria.getValue());
}
} else {
if (root.get(criteria.getKey()).getJavaType() == String.class) {
return builder.like(builder.lower(root.<String>get(criteria.getKey())),
"%" + value.toLowerCase() + "%");
} else {
return builder.equal(root.get(criteria.getKey()), value);
}
}
return null;
}
}
This method creates specification builder:
public ViewDetailSpecificationsBuilder createSearchSpecifications(ViewSearch view) {
ViewDetailSpecificationsBuilder builder = new ViewDetailSpecificationsBuilder();
if (StringUtils.isNotBlank(view.getName())) {
builder.with("name", Operation.DEFAULT, view.getName());
}
if (StringUtils.isNotBlank(view.getDescription())) {
builder.with("description", Operation.DEFAULT, view.getDescription());
}
return builder;
}
And finally I do this:
ViewDetailSpecificationsBuilder builder = createSearchSpecifications(view);
builder.with("userId", Operation.DEFAULT, userSessionHelper.getUserId());
builder.with("id", Operation.IN, viewids);
Specification<ViewDetailDom> spec = builder.build();
viewDetailDao.findAll(spec);
But I am getting following error:
"Unaware how to convert value [[5, 7, 8] : java.util.ArrayList] to requested type [java.lang.Long]; nested exception is java.lang.IllegalArgumentException: Unaware how to convert value [[5, 7, 8] : java.util.ArrayList] to requested type [java.lang.Long]"

I have resolved this problem in this way:
ViewDetailSpecification class:
if (criteria.getOperation() == Operation.IN) {
final List<Predicate> orPredicates = new ArrayList<Predicate>();
List<Long> viewIds = (List<Long>) criteria.getValue();
for (Long viewid : viewIds) {
orPredicates.add(builder.or(builder.equal(root.<String>get(criteria.getKey()), viewid)));
}
return builder.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
}

In kotlin I have the same error, I change the ArrayList to Array, with this code:
fun values(): Array<String> {
val elems = arrayListOf<String>()
return elems.toTypedArray()
}
Try you convert ArrayList to array, for java see: make arrayList.toArray() return more specific types

Related

How to group map values after Collectors.groupingBy() without using forEach

I have a list of ProductDto objects and I want to group them the similar ones using java 8 streams Collectors.groupingBy(). After grouping the records I want to combine the similar records as single productDto. To achieve this I have used map.forEach and got the expected result, but I want to avoid the forEach loop and want to know any better solution in java 8.
Below is the my Main Class code snippet.
public class GroupTest {
public static void main(String[] args) {
GroupTest t=new GroupTest();
List<ProductDto> inputDtos=t.createInputData();
List<ProductDto> resultDtos=t.getGroupedResult(inputDtos);
//writing to Excel
}
private List<ProductDto> getGroupedResult(List<ProductDto> inputDtos) {
Map<Object, List<ProductDto>> groupedMap = inputDtos.stream()
.collect(Collectors.groupingBy(ProductDto::groupSimilarProductIdentifier));
List<ProductDto> resultProductDtos=new ArrayList<>();
groupedMap.forEach((key, dtos) -> {
if (dtos.size() > 1) {
ProductDto productDto = dtos.get(0);
dtos.forEach(dto -> {
if (dto.getLap1() != null) {
productDto.setLap1(dto.getLap1());
} else if (dto.getLap2() != null) {
productDto.setLap2(dto.getLap2());
} else if (dto.getLap3() != null) {
productDto.setLap3(dto.getLap3());
}
});
resultProductDtos.add(productDto);
} else {
resultProductDtos.addAll(dtos);
}
});
return resultProductDtos;
}
private List<ProductDto> createInputData(){
List<ProductDto> dtos=new ArrayList<>();
dtos.add(new ProductDto(1L,"DELL",8,"DELL_s001",null,null));
dtos.add(new ProductDto(1L,"DELL",8,null,"DELL_s002",null));
dtos.add(new ProductDto(1L,"DELL",8,null,null,"DELL_s003"));
dtos.add(new ProductDto(1L,"HP",8,"HP_s001",null,null));
dtos.add(new ProductDto(2L,"APPLE",16,"MAC_s001",null,null));
return dtos;
}
}
This is the ProductDto class code
public class ProductDto {
private Long userId;
private String manufacter;
private int ram;
private String lap1;
private String lap2;
private String lap3;
public ProductDto(Long userId, String manufacter, int ram, String lap1, String lap2, String lap3) {
super();
this.userId = userId;
this.manufacter = manufacter;
this.ram = ram;
this.lap1 = lap1;
this.lap2 = lap2;
this.lap3 = lap3;
}
//getters and Setters
public List<Object> groupSimilarProductIdentifier() {
return Arrays.asList(userId, manufacter, ram);
}
}
Below is the screenshot image shows the input and output records. Output records is the results exactly I want it. Any alternate or better solution in java 8 which is efficient is most welcome.
After Rono comment I found the answer so posting the answer what I did in getGroupedResult method and added a new function mergetwoProduct. So this may help somebody.
Below is the code for my getGroupedResult and mergetwoProduct methods after changes.
private List<ProductDto> getGroupedResult(List<ProductDto> inputDtos) {
List<ProductDto> productdtos= new ArrayList<>(inputDtos.stream().collect(
Collectors.toMap(ProductDto::groupSimilarProductIdentifier, e -> e, (a, b) -> mergetwoProduct(a, b)))
.values());
return productdtos;
}
private ProductDto mergetwoProduct(ProductDto p1,ProductDto p2) {
if (p2.getLap1() != null) {
p1.setLap1(p2.getLap1());
} else if (p2.getLap2() != null) {
p1.setLap2(p2.getLap2());
} else if (p2.getLap3() != null) {
p1.setLap3(p2.getLap3());
}
return p1;
}

AutoProtoSchemaBuilder is not generating proto file

Updated my code as per #Ryan Emerson suggestion but still i don't see any auto-generation of Impl file and proto file
#AutoProtoSchemaBuilder(
includeClasses = { Book.class, Author.class },
schemaFileName = "library.proto",
schemaFilePath = "proto/")
interface DummyInitializer extends SerializationContextInitializer {
}
Author.class
public class Author {
private final String name;
private final String surname;
#ProtoFactory
public Author(String name, String surname) {
this.name = (String)Objects.requireNonNull(name);
this.surname = (String)Objects.requireNonNull(surname);
}
#ProtoField(
number = 1
)
public String getName() {
return this.name;
}
#ProtoField(
number = 2
)
public String getSurname() {
return this.surname;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
Author author = (Author)o;
return this.name.equals(author.name) && this.surname.equals(author.surname);
} else {
return false;
}
}
public int hashCode() {
return Objects.hash(new Object[]{this.name, this.surname});
}
}
Book.class
public class Book {
private final String title;
private final String description;
private final int publicationYear;
private final Set<Author> authors;
#ProtoFactory
public Book(String title, String description, int publicationYear, Set<Author> authors) {
this.title = (String)Objects.requireNonNull(title);
this.description = (String)Objects.requireNonNull(description);
this.publicationYear = publicationYear;
this.authors = (Set)Objects.requireNonNull(authors);
}
#ProtoField(
number = 1
)
public String getTitle() {
return this.title;
}
#ProtoField(
number = 2
)
public String getDescription() {
return this.description;
}
#ProtoField(
number = 3,
defaultValue = "-1"
)
public int getPublicationYear() {
return this.publicationYear;
}
#ProtoField(
number = 4
)
public Set<Author> getAuthors() {
return this.authors;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
Book book = (Book)o;
return this.publicationYear == book.publicationYear && this.title.equals(book.title) && this.description.equals(book.description) && this.authors.equals(book.authors);
} else {
return false;
}
}
public int hashCode() {
return Objects.hash(new Object[]{this.title, this.description, this.publicationYear, this.authors});
}
}
context-initialzer class with over-ride methods
import org.infinispan.protostream.SerializationContext;
import java.io.UncheckedIOException;
public class contextInitializer implements DummyInitializer {
#Override
public String getProtoFileName() {
return null;
}
#Override
public String getProtoFile() throws UncheckedIOException {
return null;
}
#Override
public void registerSchema(SerializationContext serCtx) {
}
#Override
public void registerMarshallers(SerializationContext serCtx) {
}
}
Then ClassA that instantiates context-initializer
public class classA {
DummyInitializer myInterface= new contextInitializer();
//Create a new cache instance
public void startCache() {
{
try {
manager = new DefaultCacheManager("src/main/resources/infinispan.xml");
GlobalConfigurationBuilder builder= new GlobalConfigurationBuilder();
builder.serialization().addContextInitializers(myInterface);
System.out.println("------------------>"+ builder.serialization().addContextInitializers(myInterface));
cache = manager.getCache();
System.out.println(cache.getName()+" is initialized ");
} catch (IOException e) {
throw new IllegalArgumentException("Failed to initialize cache due to IO error",e);
}
}
}
Maven
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-bom</artifactId>
<version>${infinispan.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.infinispan.protostream</groupId>
<artifactId>protostream-processor</artifactId>
<scope>provided</scope>
</dependency>
I am still not seeing any auto-generated proto file. Can someone tell me what am i doing wrong ?
You also need to add the org.infinispan.protostream:protostream-processor artifact as a dependency in order for code to be generated:
<dependency>
<groupId>org.infinispan.protostream</groupId>
<artifactId>protostream-processor</artifactId>
<version>4.3.2.Final</version>
</dependency>
Once that's present, a DummyInitializerImpl.java class will be generated that automatically registers the proto file and marshallers for the Book and Author classes. Remember that these classes must also have protostream annotations in order for the schema and marshallers to be generated. Please see the documentation for code examples.
There are two issues with your current code:
You have provided a DummyInitializerImpl class, but that is what should be generated by #AutoProtoSchemaBuilder.
In your DummyInitializerImpl you're trying to register the Infinispan UUIDMarshaller for the Book and Author types. This won't work as that marshaller is designed for the java UUID class.
I suspect that the two issues are due to a missunderstanding of how the code generation works. If you just required a SerializationContextInitializer for the Author and Book classes, it's not necessary to create the DummyInitializerImpl manually and you definitely don't need to utilise the UUIDMarshaller.
You are not saying which build system is used. maven maybe ? Did you add the protostream annotation processor as a dependency? Having a definite answer to these questions would help unriddle the issue of code generation. And after, we still need to find out who is supposed to initialize that dummyInitializer field.

JUnit/Spring/MongoDB: Unit test fails due to null value

I am fairly new to unit test and started writing a simple test to make sure the returned query is not null using assertJ. I am using Fongo for my unit test and although I am having no error, the returned value is always null.
This is the class to be tested:
#Repository
public class DataVersionDaoMongo extends MongoBaseDao<DataVersion> implements DataVersionDao {
#Autowired
MongoOperations mongoOperations;
public DataVersionDaoMongo() {
initType();
}
#Override
public DataVersion findByDBAndCollection(String dbName, String collectionName) {
//return mongoOperations.findOne(Query.query(Criteria.where("dbName").is(dbName).and("collectionName").is(collectionName)), DataVersion.class);
Criteria criteria = Criteria.where("dbName").is(dbName).and("collectionName").is(collectionName);
Query query = Query.query(criteria);
return mongoOperations.findOne(query, DataVersion.class);
}
}
This is my unit test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:/testApplicationContext.xml")
public class DataVersionDaoMongoTest {
#Autowired
private DataVersionDaoMongo dataVersionDaoMongo;
//private MongoOperations mongoOperations;
private DataVersion dataVersion;
#Rule
public FongoRule fongoRule = new FongoRule();
#Test
public void findByDBAndCollection() {
String dbname = "mydb";
String collectionName = "mycollection";
DB db = fongoRule.getDB(dbname);
DBCollection collection = db.getCollection(collectionName);
Mongo mongo = fongoRule.getMongo();
collection.insert(new BasicDBObject("name", "randomName"));
assertThat(dataVersionDaoMongo.findByDBAndCollection(dbname, collectionName)).isNotNull();
}
}
I am sure that
dataVersionDaoMongo.findByDBAndCollection(dbname, collectionName) is returning null (It is returning DataVersion object which is null), so the test fails. How would I actually go about and make it return DataVersion that is not null?
Here is the DataVersion class:
#Document(collection = "DataVersion")
public class DataVersion {
#Id
private String id;
private String dbName;
private String collectionName;
private String version;
private boolean isCompleted;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDbName() {
return dbName;
}
public void setDbName(String dbName) {
this.dbName = dbName;
}
public String getCollectionName() {
return collectionName;
}
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public boolean isCompleted() {
return isCompleted;
}
public void setCompleted(boolean isCompleted) {
this.isCompleted = isCompleted;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((collectionName == null) ? 0 : collectionName.hashCode());
result = prime * result + ((dbName == null) ? 0 : dbName.hashCode());
result = prime * result + (isCompleted ? 1231 : 1237);
result = prime * result + ((version == null) ? 0 : version.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;
DataVersion other = (DataVersion) obj;
if (collectionName == null) {
if (other.collectionName != null)
return false;
} else if (!collectionName.equals(other.collectionName))
return false;
if (dbName == null) {
if (other.dbName != null)
return false;
} else if (!dbName.equals(other.dbName))
return false;
if (isCompleted != other.isCompleted)
return false;
if (version == null) {
if (other.version != null)
return false;
} else if (!version.equals(other.version))
return false;
return true;
}
}
Any help would be greatly appreciated!
P.S.
This is what I am adding in my unit test class:
#Autowired
private MongoOperations mongoOperations;
Then
DataVersion dataVersion = new DataVersion();
dataVersion.setDbName("DBDataVersion");
dataVersion.setVersion("version1");
dataVersion.setCollectionName("DataVersion");
mongoOperations.insert(dataVersion);
assertThat(dataVersionDaoMongo.findByDBAndCollection(dataVersionDaoMongo.getDbName(), dataVersion.getCollectionName())).isNotNull();
The unit test passes because it is no longer returning null, but then I am not making use of Fongo anymore. I am not sure if what I am doing is right or not.
You insert the document into mycollection collection in the test but the dao queries DataVersion collection.
Also you don't define dbName and collectionName in the stored object, hence, it won't be picked by a query which targets that two fields.

Spring - NoSuchMethodException when calling a RestService

I have this simple Mapping that should return me a List objects
#RestController
#RequestMapping(value="/api")
public class ServerRESTController {
#Autowired ServerService serverService;
#RequestMapping(value="/server/{idServer}", method = RequestMethod.GET)
public ResponseEntity<Server> getFloorLatUpdate(#PathVariable int idServer){
Server server = serverService.findById(idServer);
return new ResponseEntity<Server>(server, HttpStatus.OK);
}
#RequestMapping(value="/server/list", method = RequestMethod.GET)
public ResponseEntity<List<Server>> listAllServers(){
List<Server> servers = serverService.findAllServers(-1);
return new ResponseEntity<List<Server>>(servers, HttpStatus.OK);
}
}
Server.class is a model
#Entity
#Table(name = "server")
public class Server implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private int serverId;
private Piano piano;
private String nomeServer;
private String serverIp;
private String descrizione;
private boolean online;
private Set<Interruttore> interruttori;
private String firmwareVersion;
public Server(){
}
public Server(int serverId, Piano piano, String nomeServer, String serverIp, String descrizione, boolean online,
Set<Interruttore> interruttori, String firmwareVersion){
this.serverId = serverId;
this.piano = piano;
this.nomeServer = nomeServer;
this.descrizione = descrizione;
this.serverIp = serverIp;
this.online = online;
this.interruttori = interruttori;
this.setFirmwareVersion(firmwareVersion);
}
#Id
#Column(name = "id_server", unique = true, nullable = false)
#GeneratedValue(strategy = IDENTITY)
public int getServerId() {
return serverId;
}
public void setServerId(int serverId) {
this.serverId = serverId;
}
#ManyToOne
#JoinColumn(name="id_piano")
public Piano getPiano() {
return piano;
}
public void setPiano(Piano piano) {
this.piano = piano;
}
#Column(name="nome_server")
public String getNomeServer() {
return nomeServer;
}
public void setNomeServer(String nomeServer) {
this.nomeServer = nomeServer;
}
#Column(name="server_ip")
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
#Column(name="descrizione")
public String getDescrizione() {
return descrizione;
}
public void setDescrizione(String descrizione) {
this.descrizione = descrizione;
}
#Column(name="online")
public boolean isOnline() {
return online;
}
public void setOnline(boolean online) {
this.online = online;
}
#JsonIgnore
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "server")
public Set<Interruttore> getInterruttori() {
return interruttori;
}
public void setInterruttori(Set<Interruttore> interruttori) {
this.interruttori = interruttori;
}
#Column(name = "firmware_version")
public String getFirmwareVersion() {
return firmwareVersion;
}
public void setFirmwareVersion(String firmwareVersion) {
this.firmwareVersion = firmwareVersion;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((descrizione == null) ? 0 : descrizione.hashCode());
result = prime * result + ((nomeServer == null) ? 0 : nomeServer.hashCode());
result = prime * result + (online ? 1231 : 1237);
result = prime * result + ((piano == null) ? 0 : piano.hashCode());
result = prime * result + serverId;
result = prime * result + ((serverIp == null) ? 0 : serverIp.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;
Server other = (Server) obj;
if (descrizione == null) {
if (other.descrizione != null)
return false;
} else if (!descrizione.equals(other.descrizione))
return false;
if (nomeServer == null) {
if (other.nomeServer != null)
return false;
} else if (!nomeServer.equals(other.nomeServer))
return false;
if (online != other.online)
return false;
if (piano == null) {
if (other.piano != null)
return false;
} else if (!piano.equals(other.piano))
return false;
if (serverId != other.serverId)
return false;
if (serverIp == null) {
if (other.serverIp != null)
return false;
} else if (!serverIp.equals(other.serverIp))
return false;
return true;
}
}
When trying to call for the service i'm getting:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalStateException: Method [listAllServers] was discovered in the .class file but cannot be resolved in the class object
cause by
java.lang.NoSuchMethodException: it.besmart.restcontroller.ServerRESTController.listAllServers()
I cannot understand why this happens, I have always used ResponseEntity in this way... maybe it's for the List?
Please post the whole code so we can find out.
This usually comes when the method is invoked at the wrong place or when there is a mismatch in build and runtime environments or when you miss arguments in a constructor and so on.
Also, you may want to check the files in the classpath. There may be a mismatch between compile time and actual runtime environments for some reason. For example, you say that you build it using command line. So, there may be some discrepancy there, no harm in checking.
Finally, you can check for spelling mistakes - I know that sounds strange, but case sensitivity is important.

Returning Page<Object> in Query DSL

I am using Query DSL and want my result set to return a Page Object. Is there a way to do that in Query DSL? If so Whats my query going to be looking like?
I am using JPAQuery and I have my QClasses
The Method structure is this
public Page<Object> searchPerson(String name,String phone){
Page<Object> results=null;
JPQLQuery query = new JPAQuery(entityManager);
QPerson person = QPerson.person;
//I am assuming my query would go here
results = query.from(person). ?????
return results;}
Help!
Here is my implementation for Paging with QueryDSL. A PageRequest defines the parameters for our query (limit and page):
public class PageRequest {
protected Long page = 1l;// 1 is the first page
protected Integer limit = 10;
public PageRequest(Long page, Integer limit) {
this.limit = limit;
this.page = page;
}
public Long getPage() {
return page;
}
public Integer getLimit() {
return limit;
}
public Long getOffset() {
return (page - 1l) * limit;
}
}
The Page Class contains the result (here the attribute objects) of the query and could implement methods to create nice paging links.
public class Page<T> extends PageRequest {
protected Collection<T> objects;
private Long totalCount;
private Long pageCount;
private Boolean hasPageLinkPrev;
private Boolean hasPageLinkNext;
private Collection<Long> pageLinks;
public Page(Long page, Integer limit, Long totalCount, Collection<T> objects) {
this.page = page;
this.limit = limit;
this.totalCount = totalCount;
this.objects = objects;
this.pageCount = totalCount / limit;
if (totalCount % limit > 0) {
this.pageCount = this.pageCount + 1;
}
this.hasPageLinkPrev = page > 1;
this.hasPageLinkNext = page < this.pageCount;
this.pageLinks = new ArrayList<>();
if (this.pageCount != 1) {
this.pageLinks.add(1l);
if (page > 3l) {
this.pageLinks.add(-1l);
}
if (page > 2l) {
if (page.equals(this.pageCount) && this.pageCount > 3l) {
this.pageLinks.add(page - 2l);
}
this.pageLinks.add(page - 1l);
}
if (page != 1l && !page.equals(this.pageCount)) {
this.pageLinks.add(page);
}
if (page < this.pageCount - 1l) {
this.pageLinks.add(page + 1l);
if (page == 1l && this.pageCount > 3l) {
this.pageLinks.add(page + 2l);
}
}
if (page < this.pageCount - 2l) {
this.pageLinks.add(-1l);
}
this.pageLinks.add(this.pageCount);
}
}
public Page(PageRequest pageRequest, Long totalCount, Collection<T> objects) {
this(pageRequest.getPage(), pageRequest.getLimit(), totalCount, objects);
}
public Long getTotalCount() {
return this.totalCount;
}
public Long getPageCount() {
return this.pageCount;
}
public Long getPage() {
return this.page;
}
public Integer getLimit() {
return this.limit;
}
public Boolean getHasPageLinkPrev() {
return this.hasPageLinkPrev;
}
public Boolean getHasPageLinkNext() {
return hasPageLinkNext;
}
public Collection<Long> getPageLinks() {
return pageLinks;
}
public Collection<T> getObjects() {
return objects;
}
}
With that stuf it is not very hard to create the query and put the results in our page object. One possibility is to write a generic method in the base class of the repository classes:
protected <T> Page<T> getPage(JPQLQuery<T> query, PageRequest pageRequest) {
List<T> resultList = query
.offset(pageRequest.getOffset())
.limit(pageRequest.getLimit())
.fetch();
Long totalCount = query.fetchCount();
return new Page<T>(pageRequest, totalCount, resultList);
}
In your repository class you create your query for the particular use case. Then you can use the method getPage to get the results in a Page.
public Page<Person> searchPerson(String name,
String phone,
PageRequest request){
Page<Person> results=null;
JPQLQuery<Person> query = new JPAQuery<>(entityManager);
QPerson person = QPerson.person;
query = query.from(person)
.where(person.name.eq(name)
.and(person.phone.eq(phone)));
return getPage(query, request);
}
The solution for the above was using BooleanBuilder implemented on the method above and changed the method name to return Person Object.
Please check BooleanBuilder
QPerson person= QPerson.person;
BooleanBuilder builder = this.getBuilder(name, phone,page, pageSize, sortFlag, sortItem);
PageRequest pg = getPRequest(page, pageSize);
Page<Person> pages personRepo.findAll(builder,pg);
return pages;
and then Implemented getBuilder Method for it which is the below one
public BooleanBuilder getBuilder(String name, String phone, Integer page, Integer pageSize, String sortFlag, String sortItem) {
QPerson person = QPerson.person;
BooleanBuilder builder = new BooleanBuilder();
builder.and(person.name.startsWith(name));
return builder;
}
and finally implemented the getPRequest Method as the following
public PageRequest getPRequest(Integer page, Integer pageSize) {
return new PageRequest(page, pageSize);
}
Oooooh Happy Days!

Resources