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

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.

Related

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

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/

Insert with HQL query

I want to insert a new record to MySQL.
database: enter image description here
Entity class:`package entites;
// Generated Aug 11, 2017 1:32:55 PM by Hibernate Tools 4.3.1
import java.util.Date;
/**
* UserMonhoc generated by hbm2java
*/
public class UserMonhoc implements java.io.Serializable {
private UserMonhocId id;
private Monhoc monhoc;
private User user;
private Date thoigianDk;
public UserMonhoc() {
}
public UserMonhoc(UserMonhocId id, Monhoc monhoc, User user, Date thoigianDk) {
this.id = id;
this.monhoc = monhoc;
this.user = user;
this.thoigianDk = thoigianDk;
}
public UserMonhocId getId() {
return this.id;
}
public void setId(UserMonhocId id) {
this.id = id;
}
public Monhoc getMonhoc() {
return this.monhoc;
}
public void setMonhoc(Monhoc monhoc) {
this.monhoc = monhoc;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
public Date getThoigianDk() {
return this.thoigianDk;
}
public void setThoigianDk(Date thoigianDk) {
this.thoigianDk = thoigianDk;
}
}
`
Code:
public boolean InsertStudent(String idUS, String idMH) {
try {
sf.getCurrentSession().beginTransaction();
UserMonhoc umh = new UserMonhoc();
String hql2 = "INSERT INTO User_Monhoc(user_id,mh_id) VALUES('" + idUS + "','" + idMH + "')";
System.out.println(hql2);
Query query = sf.getCurrentSession().createSQLQuery(hql2);
query.executeUpdate();
return true;
} catch (Exception e) {
return false;
}
}
it don't work.
Thank you.
Insert with HQL query
You don't use a HQL query.
This invocation :
Session.createSQLQuery(...)
creates a native SQL Query.
Anyway, you could not use INSERT in this way in HQL.
According to Hibernate documentation :
Only the INSERT INTO ... SELECT ... form is supported. You cannot
specify explicit values to insert.
But using a HQL query will not solve your problem as you want to specify values to insert.
To persist an entity, the most natural way of doing in Hibernate is invoking theSession.persist() method :
UserMonhoc umh = new UserMonhoc();
... // set fields of the object
sf.getCurrentSession().persist(umh);
But to do it, UserMonhoc of course has to be declared as an entity.
I specify it as I don't see any Hibernate annotation in your actual entity. These are maybe declared in the xml configuration...

Spring hibernate mysql can not fetch the data

In my mysql database I have a table,named:-file_upload
table structure is ;-
I have stored picture in this table..Now I want to fetch the image..
So,I have:--
#Table(name = "file_upload")
public class ProfilePic {
private long id;
private String fileName;
private byte[] data;
--setters and getters with #Column annotation---
public ProfilePic(BigInteger userId) {
super();
this.userId = userId;
}
}
my dao class is:--
public ProfilePic FetchImage(ProfilePic profilePic) {
String hql = "select data from ProfilePic where userId = :userId1 ";
logger.info( profilePic.getUserId());
Query query = (Query) sessionFactory.getCurrentSession().createQuery(hql)
.setParameter("userId1", profilePic.getUserId());
return (ProfilePic) query.uniqueResult();
}
But I am getting error:---
org.hibernate.NonUniqueResultException: query did not return a unique result: 4
why??where is the problem??
This error said that Your query returns 4 rows , that this user has 4 rows in your file_upload table so query.uniqueResult() doesn't return unique result so change query.uniqueResult() to query.List()
use query.uniqueResult() when you guarantee 100% that your query will return only one single result
I don't know if you need to get all the ProfilePic objects associated with that user id or not but you can get the list and choose the one you want
public ArrayList<ProfilePic> FetchImage(ProfilePic profilePic) {
String hql = "select data from ProfilePic where userId = :userId1 ";
logger.info( profilePic.getUserId());
Query query = (Query) sessionFactory.getCurrentSession().createQuery(hql)
.setParameter("userId1", profilePic.getUserId());
return (ArrayList<ProfilePic>) query.List();
}

Is it possible to use raw SQL within a Spring Repository

I need to use raw SQL within a Spring Data Repository, is this possible? Everything I see around #Query is always entity based.
The #Query annotation allows to execute native queries by setting the nativeQuery flag to true.
Quote from Spring Data JPA reference docs.
Also, see this section on how to do it with a named native query.
YES, You can do this in bellow ways:
1. By CrudRepository (Projection)
Spring Data Repositories usually return the domain model when using query methods. However, sometimes, you may need to alter the view of that model for various reasons.
Suppose your entity is like this :
import javax.persistence.*;
import java.math.BigDecimal;
#Entity
#Table(name = "USER_INFO_TEST")
public class UserInfoTest {
private int id;
private String name;
private String rollNo;
public UserInfoTest() {
}
public UserInfoTest(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", nullable = false, precision = 0)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "name", nullable = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Basic
#Column(name = "roll_no", nullable = true)
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
Now your Projection class is like below. It can those fields that you needed.
public interface IUserProjection {
int getId();
String getName();
String getRollNo();
}
And Your Data Access Object(Dao) is like bellow :
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.ArrayList;
public interface UserInfoTestDao extends CrudRepository<UserInfoTest,Integer> {
#Query(value = "select id,name,roll_no from USER_INFO_TEST where rollNo = ?1", nativeQuery = true)
ArrayList<IUserProjection> findUserUsingRollNo(String rollNo);
}
Now ArrayList<IUserProjection> findUserUsingRollNo(String rollNo) will give you the list of user.
2. Using EntityManager
Suppose your query is "select id,name from users where roll_no = 1001".
Here query will return an object with id and name column. Your Response class is like bellow:
Your Response class is like this:
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 an Object Array and set data with the 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 roll_no = ?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 get EntityManager and call this getUserByRoll(EntityManager entityManager,String rollNo) function. The calling procedure is given below:
Here is the Imports
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
get EntityManager from this way:
#PersistenceContext
private EntityManager entityManager;
UserObject userObject = getUserByRoll(entityManager,"1001");
Now you have data in this userObject.
Note:
query.getSingleResult() return a object array. You have to maintain the column position and data type with the query column position.
select id,name from users where roll_no = 1001
query return a array and it's [0] --> id and [1] -> name.
More info visit this thread and this Thread
Thanks :)
It is possible to use raw query within a Spring Repository.
#Query(value = "SELECT A.IS_MUTUAL_AID FROM planex AS A
INNER JOIN planex_rel AS B ON A.PLANEX_ID=B.PLANEX_ID
WHERE B.GOOD_ID = :goodId",nativeQuery = true)
Boolean mutualAidFlag(#Param("goodId")Integer goodId);
we can use createNativeQuery("Here Native SQL Query ");
for Example :
Query q = em.createNativeQuery("SELECT a.firstname, a.lastname FROM Author a");
List<Object[]> authors = q.getResultList();
This is how you can use in simple form
#RestController
public class PlaceAPIController {
#Autowired
private EntityManager entityManager;
#RequestMapping(value = "/api/places", method = RequestMethod.GET)
public List<Place> getPlaces() {
List<Place> results = entityManager.createNativeQuery("SELECT * FROM places p limit 10").getResultList();
return results;
}
}
It is also possible to use Spring Data JDBC, which is a fully supported Spring project built on top of Spring Data Commons to access to databases with raw SQL, without using JPA.
It is less powerful than Spring Data JPA, but if you want lightweight solution for simple projects without using a an ORM like Hibernate, that a solution worth to try.

JPA Typed Search Queries

I have a rather big model Applicant:
public class Applicant{
private Long id
private String name;
...
...
}
To populate a selection list, I need a list of (id, name) tuples and I use this search query:
public List getNames() {
Query query = em.createQuery("select a.id, a.name from Applicant a");
return query.getResultList();
}
However, I get a list of Object[]'s and I don't really want to convert these in the business layer to the corresponding types (Long and String). What is the best way to approach this? Should I iterate through the list and manually do the type conversion before returning it? Or should I make a helper class:
public class ApplicantTuple{
public Long id
public String name;
public Application(Long id, String name) {
...
}
}
and then have a search query:
Query query = em.createQuery("select NEW my.model.ApplicantTuple(a.id, a.name) from Applicant a");
Or is there a better way to type search queries?
Since you're apparently using JPA2, use the type-safe methods:
public List<Applicant> getApplicants() {
TypedQuery<Applicant> query = em.createQuery(
"select a.id, a.name from Applicant a",
Applicant.class
);
return query.getResultList();
}
Then just use the Objects:
for(Applicant app: getApplicants()){
selectionList.populate(app.getName(), app.getId());
}

Categories

Resources