I want to get a page of results using follwing Java code:
Page<MyDTO> page = repo.findAllOrderByCreatedDate(new PageRequest(pageNumber,pageSize));
In MyDTO I have:
#Entity
class MyDTO{
#Id
private Long id;
private LocalDateTime createdDate;
//getters setters
}
What I get is:
No parameter available for part createdDate SIMPLE_PROPERTY (1):
[Is, Equals].; nested exception is java.lang.IllegalArgumentException:
How to combine paging and sortig with Spring Data?
You can use another constructor of class PageRequest:
Page<MyDTO> page = repo.findAll(new PageRequest(pageNumber,pageSize, new Sort("createdDate")));
Related
I'm trying to display a table listing the Country codes (iso3166) in a postgresql db onto an html page using Spring Boot and Angular, the parameter name in the http response lists "number" when instead I want it to list "nbr".
The SQL table has 4 columns
name (varchar) unique
alpha2 (varchar) PK unique
alpha3 (varchar) unique
nbr (int4)
My Spring Boot Models is the following:
#Entity
#Table(name = "iso3166")
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private String alpha2;
#Column(name = "name")
private String name;
#Column(name = "alpha3")
private String alpha3;
#Column(name = "nbr")
private int nbr;
public Country()
{
}
public Country(String name, String alpha2, String alpha3, int nbr)
{
this.name = name;
this.alpha2 = alpha2;
this.alpha3 = alpha3;
this.nbr = nbr;
}
/*
getters and settings + toString()
*/
The repository uses JPARepository
public interface ICountryRepository extends JpaRepository<Country, String> {
}
And the Controller has only the findAll() method
#RestController
#RequestMapping({"/api"})
public class CountryController {
#Autowired
ICountryRepository countryRepository;
#GetMapping
public List<Country> findAll(){
List<Country> country = countryRepository.findAll();
return country;
}
}
Running spring-boot and opening localhost in chrome, the table shows up just fine.
However, looking at the Response tab under Network, it shows up like this
Shows the same thing if I go to http://localhost:8080/api
[{"alpha2":"AX","name":"AALAND ISLANDS","alpha3":"ALA","number":248},{"alpha2":"AF","name":"AFGHANISTAN","alpha3":"AFG","number":4},{"alpha2":"AL","name":"ALBANIA","alpha3":"ALB","number":8},{"alpha2":"DZ","name":"ALGERIA","alpha3":"DZA","number":12},{"alpha2":"AS","name":"AMERICAN SAMOA","alpha3":"ASM","number":16},{"alpha2":"AD","name":"ANDORRA","alpha3":"AND","number":20},{"alpha2":"AO","name":"ANGOLA","alpha3":"AGO","number":24},
Why does the Http Response return the "nbr" field as "number" instead? And how can I change it to show up as "nbr" in the Http response? Does something happen in the background in Spring Boot when formulating the http response that I can't control?
It is a number because you defined it as a number here, in Country entity:
#Column(name = "nbr")
private int nbr;
The best solution is to create another object which is used for HTTP communication. For example: CountryDTO.
In CountryDTO you can define nbr field as String.
Then you just have to create a mapping between Country and CountryDTO objects.
Why you should always do like this:
You should never send Entities directly to the client.
It keeps your code clean and separated: One object is responsible for holding the database model, and another is responsible for communicating with the client. It is now the same, and it is just pure luck.
Found out what happened, although I don't know the specifics.
spring uses Jackson to serialize, and Jackson uses by default public getters to serialize and name data.
Since I named the nbr getter/setters as getNumber() and setNumber, changing it to getNbr() and setNbr() respectively solved the issue.
I'm trying to create a reference to another model in Spring MognoDB.
I have a list of documents previously inserted into MongoDB using Mongoose so the references look like this:
{
...
address: ObjectId("5f596acb8ea1d54128016e97")
}
Following the Spring MongoDB documentation, I created two models:
#Document(collection = "person")
public class Person{
#Id
private String id;
... other attributes
#DBRef
private Address address;
}
Second model:
#Document(collection = "address")
public class Address{
#Id
private String id;
... other attributes
}
However this fails to return a document, showing the following error:
No converter found capable of converting from type [org.bson.types.ObjectId] to type [....models.Address]
Any idea how to solve this problem?
I also tried changing the id type to ObjectId but still getting the same error.
I want to fetch selected columns, preferably dynamically.
For now, I'm specifying static columns - id, title, description.
Category.java
#Entity(name="Category")
#Table(name="categories")
public class Category {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String slug;
private String title;
private String description;
private String preview_image;
private int isFeatured;
/* Getters, setters etc */
}
CategoryRepository.java
public interface CategoryRepository extends JpaRepository<Category, Long> {
#Query(
value = "SELECT id, title, description FROM categories",
nativeQuery = true
)
List<Category> findAll();
}
This gives the error:
Column 'is_featured' not found. Exception class: class
org.springframework.dao.InvalidDataAccessResourceUsageException
Exception [could not execute query; SQL [SELECT id, title, description
FROM categories]; nested exception is
org.hibernate.exception.SQLGrammarException: could not execute query]
Any idea how this error can be resolved? I was thinking of using another model instead of Category but I need to make the fields dynamic later on. It's hard to make model class if I'm unaware of which fields to return.
Also, is there a way I can make this #Query code dynamic such that it returns columns mentioned in parameter?
Any help would be appreciated. Thanks in advance! :)
Its because of the naming strategy of Spring and Hibernate. It will convert camelCase to SNAKE_CASE by default. So in your case its isFeatured -> is_featured.
If you dont want to change the naming strategy just add #Column("isFeatured") on your property. This will override the default behavior of this property.
Here you can find more Spring Boot + JPA : Column name annotation ignored
Regarding dynamic query. You should look up the features in the documentation of Spring-data-jpa and about querydsl
I'm trying to implement a Repository to work with Views. The fact is that I'm trying to use the SimpleJpaRepository implementation, but I'm getting a lot of errors on execution time because my DTO is not an #Entity. It is only a #Table, and it seems that this kind of elements are not mapped into the Metamodel of JPA.
This is my DTO:
#Table(name = "v_language")
public class VLanguage {
#Column(name = "isocode")
private String isocode;
#Column(name = "name")
private String name;
#Column(name = "isdefault")
private String isdefault;
// getters and setters
...
}
I tried to define a customized base repository with minimal functionality (only a findAll() method) with the same implementation of SimpleJpaRepository, but when building the Query it fails when doing:
Root<U> root = query.from(domainClass);
With this exception:
Caused by: java.lang.IllegalArgumentException: Not an entity: class es.prodevelop.pui.common.jpa.model.views.dto.VLanguage
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:194)
at org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:124)
at org.hibernate.jpa.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:156)
at es.prodevelop.pui.common.jpa.configuration.AbstractRepository.applySpecificationToCriteria(AbstractRepository.java:213)
at es.prodevelop.pui.common.jpa.configuration.AbstractRepository.getQuery(AbstractRepository.java:174)
at es.prodevelop.pui.common.jpa.configuration.AbstractRepository.findAll(AbstractRepository.java:151)
...
Does anybody know how to solve it?
you are missing the #Entity annotation.
please annotate your class and try again.
I am pretty new in Spring and I have the following doubt. In a web application I have the following entity class that map a database table:
#Entity
#Table(name = "KM_PROJECT_INFO")
public class KM_ProjectInfo implements Serializable {
#Id
#GeneratedValue
private Long idProjectInfo;
#Column(name = "name")
private String name;
#Column(name = "technology")
private String technology;
#ManyToOne
#JoinColumn(name = "idCountry")
private KMCountry country;
#Column(name = "power")
private long power;
#Column(name = "cod")
private String cod;
#ManyToOne
#JoinColumn(name = "idProjectInfoStatus")
private KM_ProjectInfoStatus status;
#Column(name = "folderTech")
private long folderTech;
#Column(name = "folderProject")
private long folderProject;
// GETTER & SETTER
}
In a view there is a form where the user can insert the value of the fields of the previous entity class. When the user click the submit button of this form it is performed an action of a controller (in the specific case it is a Struts 2 action controller, but I think that this is not important).
In this action I have to retrieve the value inserted by the user into the form fields and use these values to set the matching fields of the previous entity class, then I have to persist it on the DB using Hibernate.
So my doubt is: the previous entity class is annoted using #Entity annotation. Can I simply inject it into my controller? Can I inject an instance of a class annoted with #Entity?
Tnx
You can make this happen', won't happen automatically as #Entity does not mark a class to be a spring bean. You can make it a Spring bean, but than Spring framework would take over managing the life-cycle of an entity object which should be an exclusive role of the JPA framework. Making this work in a sensible way would be a horrible struggle.
Luckily for you, from what you described you don't need to do this, simply create an instance of your Entity, populate it with form params and pass on the object to your service or DAO.
You just have to create object using simple java object creation:
KM_ProjectInfo obj = new KM_ProjectInfo();
And then use setter method to set properties and do database operations. You don't need to use spring bean creation.
You don't need to inject this as a spring bean into your controller.
Just create an instance of the Entity.
Set the entity fields as per the form parameters.
Persist the entity in the DB.