org.hibernate.hql.internal.ast.QuerySyntaxException: REPORT Table is not mapped - java

I have a simple API that expects three parameters and sends a response back, whenever I try to pass the three parameters I end up with an error
org.hibernate.hql.internal.ast.QuerySyntaxException: REPORTS
is not mapped [SELECT e FROM REPORTS e WHERE e.country =
:country AND e.projectId = :projectId AND e.code = :code]
The Model class
#Entity(name = "REPORTS")
#Table(name = "REPORTS")
public class DashboardModel {
public String Country;
public String Project;
public String HtmlContent;
public String FileName;
public String Code;
public String TeamLead;
public String Team;
public DateTime CreateDate;
public DateTime UpdateDate;
//boiler plate code
My Controller
#GetMapping(path = "/report/reportsheet")
public ResponseEntity<String> getReportSheet(#RequestParam("country") String country,
#RequestParam("projectId") String projectId,
#RequestParam("clusterNumber") String clusterNumber){
String report = dashboardService.getReport(country,projectId,clusterNumber);
//String report_ = wallboardService.getStateReportLabelByCountryProjectAndType(country,projectId,reportType);
return ResponseEntity.status(HttpStatus.OK).body(report);
My Service
public String getReport(String country,String projectId,String code){
TypedQuery<DashboardModel> query = entityManager.createQuery(
"SELECT e FROM REPORTS e WHERE e.country = :country AND e.projectId = :projectId AND e.code = :clusterNumber" , DashboardModel.class);
List<DashboardModel> dashboard = query
.setParameter("country", country)
.setParameter("projectId", projectId)
.setParameter("clusterNumber", code)
.getResultList();
return String.valueOf(dashboard);
}
How should I map the table correctly?

You have to use entity class names like DashboardModel in the JPQL and a table name REPORTS in the SQL.
The second parameter DashboardModel.class in the createQuery() is not related to entity class name in the SELECT clause.
You can just use createQuery(jpql) with one parameter, but that method returns a List without element type. So what the second parameter DashboardModel.class for.
You don't need to specify table name here #Entity(name = "REPORTS")
just #Entity

I guess the entity is not in a package that is scanned by Spring Boot. Here is an article about this: https://springbootdev.com/2017/11/13/what-are-the-uses-of-entityscan-and-enablejparepositories-annotations/

Related

Data is not passed into list by JpaRepository

I'm trying to get data from MySql Database by custom jpql #query method. I'm not receiving any error, but my list of results is empty.
In console hibernate show results like this:
Hibernate: select flight0_.id as id1_0_, flight0_.arrival_city as arrival_2_0_, flight0_.date_of_departure as date_of_3_0_, flight0_.departure_city as departur4_0_, flight0_.estimated_departure_time as estimate5_0_, flight0_.flight_number as flight_n6_0_, flight0_.operating_airlines as operatin7_0_ from flight flight0_ where flight0_.departure_city=? and flight0_.arrival_city=? and flight0_.date_of_departure=?
I tried to add annotations in model classes like #Column but nothing changed.
Typing lower or uppercase, still nothing. Any suggestions on how to solve this problem?
In this link you can see how my JSP pages, database table and view in the browser looks like https://imgur.com/a/uwBoDmI
#Entity
public class Flight extends AbstractEntity{
private String flightNumber;
private String operatingAirlines;
private String departureCity;
private String arrivalCity;
private Date dateOfDeparture;
private Timestamp estimatedDepartureTime;
Below are getters and setters for those fields.
public interface FlightRepository extends JpaRepository<Flight, Long> {
#Query("from Flight where departureCity=:departureCity and arrivalCity=:arrivalCity and dateOfDeparture=:dateOfDeparture")
List<Flight> findFlights(#Param("departureCity") String from, #Param("arrivalCity") String to,
#Param("dateOfDeparture") Date departureDate);
}
#Controller
public class FlightController {
#Autowired
FlightRepository flightRepository;
#RequestMapping("findFlights")
public String findFlights(#RequestParam("from") String from,#RequestParam("to") String to,
#RequestParam("departureDate") #DateTimeFormat(pattern = "MM-dd-yyyy") Date departureDate, ModelMap modelMap)
{
List<Flight> findFlights = flightRepository.findFlights(from, to, departureDate);
modelMap.addAttribute("flights",findFlights);
for (Flight flightTMP : findFlights) {
System.out.println(flightTMP);
}
return "displayFlights";
}
}

Hibernate query to get a different user table data not working

I am trying to simply fetch the records from a table with the following scenario:
User: abc is the one with which I am loggin into my db it has the rights to select.
Table I am trying to access is xyz.customer, DB user xyz has this table customer.
The error that I am getting is that entity not found. even the I have clearly mentioned my class in the package scan. I tried making SqlResultSetMapping and then it said not found again. I put it in another entity class which is working fine and it still said SqlResultSetMapping not found. My code is as follow:
The code where I am calling it and gives error:
List<SampleClass> sampleClass=
entityIBSManager.createNativeQuery("select * from xyz.customer","CustomerMapping").getResultList();
The code of my entity class:
#Entity
#Table(name = "CUSTOMER", catalog = "XYZ")
#NamedQuery(name = "SampleClass.findAll", query = "select p from SampleClass p")
#SqlResultSetMapping(
name = "CustomerMapping",
entities = #EntityResult(
entityClass = SampleClass.class,
fields = {
#FieldResult(name = "customerNo", column = "CUSTOMER_ID"),
#FieldResult(name = "countryCode", column = "COUNTRY_CODE"),
#FieldResult(name = "status", column = "STATUS")}))
public class SampleClass implements Serializable {
#Id
#Column(name="CUSTOMER_ID")
private Long customerNo;
#Id
#Column(name="COUNTRY_CODE")
private String countryCode;
#Column(name="STATUS")
private int status;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public Long getCustomerNo() {
return customerNo;
}
public void setCustomerNo(Long customerNo) {
this.customerNo = customerNo;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
#Override
public String toString() {
return "PurgeCustomersIBS [customerNo=" + customerNo + ", countryCode=" + countryCode + ", status=" + status + "]";
}
}
In My DB table I have a composite key combination of country code and customer no.
and I have tried using the direct call to my named query and it gives the error of no named query found.
Thankyou for your help in advance.
Here is my stacktrace
07:57:12.006 [readTask_Worker-3] ERROR org.quartz.core.JobRunShell - Job DEFAULT.cSVFileJob threw an unhandled Exception: java.lang.IllegalArgumentException: No query defined for that name [PurgeCustomersIBS.findAll] at org.hibernate.jpa.spi.AbstractEntityManagerImpl.buildQueryFromName(AbstractEntityManagerImpl.java:753) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final] at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createNamedQuery(AbstractEntityManagerImpl.java:890) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]

Spring Data JPA Unable to locate Attribute with the given name

I was trying to use Spring Data JPA on Spring Boot and I kept getting error, I can't figure out what the problem is:
Unable to locate Attribute with the the given name [firstName] on
this ManagedType [com.example.h2demo.domain.Subscriber]
FirstName is declared in my entity class. I have used a service class with DAO before with different project and worked perfectly.
My Entity class (getters and setters are also in the class) :
#Entity
public class Subscriber {
#Id #GeneratedValue
private long id;
private String FirstName,LastName,Email;
public Subscriber(long id, String firstName, String lastName, String email) {
this.id = id;
this.FirstName = firstName;
this.LastName = lastName;
this.Email = email;
}
}
...
My Repository Class
#Component
public interface SubscriberRepository extends JpaRepository<Subscriber,Long> {
Subscriber findByFirstName(String FirstName);
Subscriber deleteAllByFirstName(String FirstName);
}
My Service Class
#Service
public class SubscriberService {
#Autowired
private SubscriberRepository subscriberRepository;
public Subscriber findByFirstName(String name){
return subscriberRepository.findByFirstName(name);
}
public Subscriber deleteAllByFirstName(String name){
return subscriberRepository.deleteAllByFirstName(name);
}
public void addSubscriber(Subscriber student) {
subscriberRepository.save(student);
}
}
And My Controller class:
#RestController
#RequestMapping("/subscribers")
public class SubscriberController {
#Autowired
private SubscriberService subscriberService;
#GetMapping(value = "/{name}")
public Subscriber findByFirstName(#PathVariable("name") String fname){
return subscriberService.findByFirstName(fname);
}
#PostMapping( value = "/add")
public String insertStudent(#RequestBody final Subscriber subscriber){
subscriberService.addSubscriber(subscriber);
return "Done";
}
}
Try changing private String FirstName,LastName,Email; to private String firstName,lastName,email;
It should work.
findByFirstName in SubscriberRepository tries to find a field firstName by convention which is not there.
Further reference on how properties inside the entities are traversed https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-property-expressions
The same problem was when i had deal with Spring Data Specifications (https://www.baeldung.com/rest-api-search-language-spring-data-specifications)
Initial piece of code was:
private Specification<Project> checkCriteriaByProjectNumberLike(projectNumber: String) {
(root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("project_number"), "%" + projectNumber)
}
The problem was in root.get("project_number"). Inside the method, I had to put the field name as in the model (projectNumber), but I sent the field name as in the database (project_number).
That is, the final correct decision was:
private Specification<Project> checkCriteriaByProjectNumberLike(projectNumber: String) {
(root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("projectNumber"), "%" + projectNumber)
}
After I change my entity class variables from capital letter to small letter for instance Username to username the method Users findByUsername(String username); is working for me now .
As per specification , the property names should start with small case.
...The resolution algorithm starts with interpreting the entire part (AddressZipCode) as the property and checks the domain class for a property with that name (uncapitalized)....
It will try to find a property with uncapitalized name. So use firstName instead of FristName and etc..

Override Pageable findAll for selecting fewer columns in Spring Data Rest

How to Override spring data repository to select only selected columns when going to pages that are discovered from /api page in spring data rest.
I added findAll as below -
public interface UserRepository extends BaseRepository<User, Integer>, UserRepositoryCustom {
#Query("select u from User u where email = :email and password = :password")
#Cacheable(value = "user-cache", key = "#user.login")
#RestResource(exported = false)
public User findUserByEmailAndPassword(#Param("email") String email, #Param("password") String password);
#RestResource(rel = "byEmail", path = "byEmail")
public User findUserByEmail(#Param("email") String email);
#RestResource(rel = "byPhone", path = "byPhone")
public User findUserByPhone(#Param("phone") String phone);
#Override
#Query("select u.id,u.email,u.phone from User u ")
public Page<User> findAll(Pageable pageable);
}
/api/users is giving an error -
{"cause":null,"message":"PersistentEntity must not be null!"}
I created a UserSummaryProjection class in same package as User
#Projection(name = "summary", types = User.class)
public interface UserSummaryProjection {
Integer getId();
String getEmail();
}
Then, going at /api/users or /users/3?projection=summary gives me desired result without changing the Repository.
Selecting subelements of User and still creating a User is somewhat counterintuitive.
I would create another entity for example UserDetails, that will be mapped by the same table with the same mapping.
public class UserDetails {
private int uid;
private String email;
private String phone;
}
And create a Repository, based on this new Entity.

use of entityManager.createNativeQuery(query,foo.class)

I would like to return a List of Integers from a
javax.persistence.EntityManager.createNativeQuery call
Why is the following incorrect?
entityManager.createNativeQuery("Select P.AppID From P", Integer.class);
specifically why do I get "...Unknown entity: java.lang.Integer"
Would I have to create an entity class that has a single field that is an Integer ?
Thanks
What you do is called a projection. That's when you return only a scalar value that belongs to one entity. You can do this with JPA. See scalar value.
I think in this case, omitting the entity type altogether is possible:
Query query = em.createNativeQuery( "select id from users where username = ?");
query.setParameter(1, "lt");
BigDecimal val = (BigDecimal) query.getSingleResult();
Example taken from here.
That doesn't work because the second parameter should be a mapped entity and of course Integer is not a persistent class (since it doesn't have the #Entity annotation on it).
for you you should do the following:
Query q = em.createNativeQuery("select id from users where username = :username");
q.setParameter("username", "lt");
List<BigDecimal> values = q.getResultList();
or if you want to use HQL you can do something like this:
Query q = em.createQuery("select new Integer(id) from users where username = :username");
q.setParameter("username", "lt");
List<Integer> values = q.getResultList();
Regards.
Here is a DB2 Stored Procidure that receive a parameter
SQL
CREATE PROCEDURE getStateByName (IN StateName VARCHAR(128))
DYNAMIC RESULT SETS 1
P1: BEGIN
-- Declare cursor
DECLARE State_Cursor CURSOR WITH RETURN for
-- #######################################################################
-- # Replace the SQL statement with your statement.
-- # Note: Be sure to end statements with the terminator character (usually ';')
-- #
-- # The example SQL statement SELECT NAME FROM SYSIBM.SYSTABLES
-- # returns all names from SYSIBM.SYSTABLES.
-- ######################################################################
SELECT * FROM COUNTRY.STATE
WHERE PROVINCE_NAME LIKE UPPER(stateName);
-- Cursor left open for client application
OPEN Province_Cursor;
END P1
Java
//Country is a db2 scheme
//Now here is a java Entity bean Method
public List<Province> getStateByName(String stateName) throws Exception {
EntityManager em = this.em;
List<State> states= null;
try {
Query query = em.createNativeQuery("call NGB.getStateByName(?1)", Province.class);
query.setParameter(1, provinceName);
states= (List<Province>) query.getResultList();
} catch (Exception ex) {
throw ex;
}
return states;
}
Suppose your query is "select id,name from users where rollNo = 1001".
Here query will return a object with id and name column.
Your Response class is like bellow:
public class UserObject{
int id;
String name;
String rollNo;
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
here UserObject constructor will get a Object Array and set data with object.
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
Your query executing function is like bellow :
public UserObject getUserByRoll(EntityManager entityManager,String rollNo) {
String queryStr = "select id,name from users where rollNo = ?1";
try {
Query query = entityManager.createNativeQuery(queryStr);
query.setParameter(1, rollNo);
return new UserObject((Object[]) query.getSingleResult());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
Here you have to import bellow packages:
import javax.persistence.Query;
import javax.persistence.EntityManager;
Now your main class, you have to call this function.
First you have to get EntityManager and call this getUserByRoll(EntityManager entityManager,String rollNo) function. Calling procedure is given bellow:
#PersistenceContext
private EntityManager entityManager;
UserObject userObject = getUserByRoll(entityManager,"1001");
Now you have data in this userObject.
Here is Imports
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
Note:
query.getSingleResult() return a array. You have to maintain the column position and data type.
select id,name from users where rollNo = ?1
query return a array and it's [0] --> id and [1] -> name.
For more info, visit this Answer
Thanks :)
JPA was designed to provide an automatic mapping between Objects and a relational database. Since Integer is not a persistant entity, why do you need to use JPA ? A simple JDBC request will work fine.

Categories

Resources