Table is not Mapped In HQL query - java

My class begins with:
#Entity
#Table(name = "validate_info", catalog = "company")
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#id")
public class ValidateInfo implements java.io.Serializable{
And my HQL Query:
List<ValidateInfo> lResult = null;
String lHql = " from ValidateInfo vi "
+ " where vi.document.idDocument in (:documentsList) "
+ " and vi.idEntityType = :idEntityType";
Query lQuery = pSession.createQuery(lHql);
lQuery.setParameterList("documentsList", pDocumentsList);
lQuery.setParameter("idEntityType", pIdEntityType);
lResult = lQuery.list();
The error I get:
[T0028][SEVER] .web.Control.execute() RunService returns Exception ValidateInfo is not mapped [ from ValidateInfo vi where vi.document.idDocument in (:documentsList) and vi.idEntityType = :idEntityType]
[T0028][SEVER] .web.Control.manageError() java.util.HashMap cannot be cast to java.util.List
Can you guys help me? I don't know why i get the "not Mapped" error, the name of the HQL query table is the same as the classname.

When you write an HQL query you must write the complete path of your used class.
So you can replace your code as follow:
String lHql = " from " + ValidateInfo.class.getName() + " vi "
+ " where vi.document.idDocument in (:documentsList) "
+ " and vi.idEntityType = :idEntityType";

Related

Spring boot jpa query can't update field

I have an update query on hibernate on this table
class PackEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String status;
private String oldStatus;
#ManyToOne
#JoinColumn(name = "order_id")
private OrderEntity order;
...
}
And on OrderEntity I have there another relationship to another table when I have machine names.
On the JPA repository, I have the query. Basically first I search by machine and status and then I want to update the old status to put the current value of the status field and in status to put the new status. This is it:
#Transactional
#Modifying(clearAutomatically = true)
#Query("UPDATE PackEntity p " +
"SET p.oldStatus= p.status, p.status = ?3 " +
"WHERE p.id IN " +
" ( SELECT p2" +
" FROM PackEntity p2" +
" JOIN p2.order " +
" JOIN p2.order.machine" +
" WHERE p2.order.machine.name = ?1 AND p2.status = ?2)")
List<PackEntity > updateAllWithStatusByMachineNameAndStatus(String machineName, String status, String newStatus);
Now I'm having this error .QueryExecutionRequestException: Not supported for DML operations [UPDATE com.pxprox.entities.PackEntity with root cause ...
Why not create a method that does this for you? Initializing the entity and updating everything, changes will be flushed automatically at the end of the transaction. You can have a look at updating entity with spring-data-jpa
It should basically be something like:
#Autowired
private PackEntityRepository packEntityRepository;
public void updatePackEntity(PackEntity newPE) {
PackEntity packEntity = packEntityRepository.findById(newPE.getId());
packEntity.setOldStatus = packEntity.getStatus();
packEntity.setStatus = newPE.getStatus();
packEntityRepository.save(packEntity);
}
The return type of the method is wrong and also the query should be a little adapted. Use the following:
#Transactional
#Modifying(clearAutomatically = true)
#Query("UPDATE PackEntity p " +
"SET p.oldStatus = p.status, p.status = ?3 " +
"WHERE EXISTS " +
" ( SELECT 1" +
" FROM PackEntity p2" +
" JOIN p2.order o " +
" JOIN o.machine m" +
" WHERE m.name = ?1 AND p2.status = ?2 AND p2.id = p.id)")
void updateAllWithStatusByMachineNameAndStatus(String machineName, String status, String newStatus);
or even better
#Transactional
#Modifying(clearAutomatically = true)
#Query("UPDATE PackEntity p " +
"SET p.oldStatus = p.status, p.status = ?3 " +
"WHERE p.status = ?2 AND EXISTS " +
" ( SELECT 1" +
" FROM p.order o " +
" JOIN o.machine m" +
" WHERE m.name = ?1)")
void updateAllWithStatusByMachineNameAndStatus(String machineName, String status, String newStatus);

How to generate entity class without create table automatic

I created some reports for my system, and that report is made up of many tables. For this, I create a Domain class with an #Entity annotation and implement a JpaRepository repository, I'm using the native query with #Query, as shown below.
My problem is that for each domain class a table is being created by hibernate, how do I stop it?
My Domain class:
#Entity
#Immutable
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#IdClass(WidgetDailyReportCompositeKey.class)
public class WidgetDailyReportDomain{
#Id
#Column(updatable = false, insertable = false)
private UUID id_construction;
#Id
#Column(updatable = false, insertable = false)
private String name;
#Id
#Column(updatable = false, insertable = false)
private Date dt_cost;
#Column(updatable = false, insertable = false)
private Double total;
}
My Repository:
public interface WidgetRepository extends JpaRepository<WidgetDailyReportDomain, UUID>{
#Query(value = " SELECT ct.id AS id_construction, " +
" ct.name, " +
" sm.dt_service AS dt_cost, " +
" sum(smi.nu_value * stiv.amount) AS total " +
" FROM service_measurement sm " +
" INNER JOIN service_measurement_item smi ON smi.id_service_measurement = sm.id " +
" INNER JOIN service s ON s.id = sm.id_service " +
" INNER JOIN service_type_item_service stiv ON stiv.id_service = sm.id_service " +
" AND stiv.id_service_type_item = smi.id_service_item " +
" INNER JOIN construction ct ON ct.id = s.id_construction " +
" WHERE s.id_construction IN ( " +
" select s.id_construction " +
" from service_measurement sm " +
" INNER JOIN service_measurement_item smi ON smi.id_service_measurement = sm.id " +
" INNER JOIN service s ON s.id = sm.id_service " +
" INNER JOIN service_type_item_service stiv ON stiv.id_service = sm.id_service " +
" AND stiv.id_service_type_item = smi.id_service_item " +
" INNER JOIN construction ct on ct.id = s.id_construction " +
" WHERE sm.dt_service BETWEEN :minDate AND :maxDate " +
" GROUP BY s.id_construction " +
" ORDER BY sum(smi.nu_value * stiv.value) DESC " +
" limit :limit " +
" ) " +
" AND sm.dt_service BETWEEN :minDate AND :maxDate " +
" GROUP BY ct.id, sm.dt_service " +
" HAVING sum(smi.nu_value * stiv.amount) > 0 " +
" ORDER BY sm.dt_service;", nativeQuery = true)
List<WidgetDailyReportDomain> findTopExpensiveConstruction(#Param("minDate") Date minDate, #Param("maxDate") Date maxDate, #Param("limit") int limit);
//....
Your WidgetDailyReportDomain is actually projection. You don't need to mark it as #Entity.
And your #Query could belong to any other really existing repository.
You can remove all the javax.persistence annotations like #Column, #Id, #Entity. These annotations represent properties of a table, which you seem to not want it to be.
Then you can use the WidgetDailyReportDomain object as a DTO to be your projection and not have it attached to the EntityManager:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.dtos
EDIT: Also, do not forget to build a constructor for that object so that Spring JPA loads the values into the object (like described on the documentation).
If you don't want to build a constructor, maybe you can change it into an interface and use it as your projection: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections.interfaces
It looks like you're using Spring due to the JpaRepository in your question.
If you're using Spring Boot, then you can add
spring:
jpa:
hibernate:
ddl-auto: none
to your application.yml file, or
spring.jpa.hibernate.ddl-auto=none
to your application.properties file.
If you're using a persistence.xml file, you could add a property to disable it there, too:
<property name="hibernate.hbm2ddl.auto" value="none"/>
Disabling the generation of the schema tables like this means that you'll have to make sure they're created by some other means before your application will work, though.
After #Zagarh answer, i did a lith of search about DTO, and i came up with a not very elegant solution, but that is working:
The Domain class :
public class WidgetDailyReportDomain{
private UUID id_construction;
private String name;
private Date dt_cost;
private Double total;
}
I have to create a custom result mapping, for the JPA be able of mapping de result, i use the annotation #SqlResultSetMapping. But for some reason she is only identify in a class that is annotated with # Entity. For not to get disorganized, i create a class exclusive to annotation with # SqlResultSetMapping, because i gona have a lot of mapping to do. The class looked like this:
#MappedSuperclass
#SqlResultSetMapping(
name = "widget_daily_mapping",
classes = {
#ConstructorResult(
targetClass = WidgetDailyReportDomain.class,
columns = {
#ColumnResult(name="id_construction", type = UUID.class),
#ColumnResult(name = "name", type = String.class),
#ColumnResult(name = "dt_cost", type = Date.class),
#ColumnResult(name = "total", type = Double.class)
}
)
}
)
public abstract class ResultSetMappingConfig {
}
And then i create a custom implementation of Jpa Repository
public interface WidgetRepositoryCustom {
List<WidgetDailyReportDomain> findTopExpensiveConstruction(Date minDate, Date maxDate, int limit);
}
#Repository
#Transactional(readOnly = true)
public class AR_serviceRepositoryImpl implements AR_serviceRepositoryCustom{
#PersistenceContext
private EntityManager em;
#Override
public List<AR_serviceDomain> getListOfService(UUID id_construction) {
Query query = em.createNativeQuery("
//Native Query Here...
", "widget_daily_mapping");// Put the result mapping Here
query.setParameter(1, id_construction //..Parameters Here);
return query.getResultList();
}
}
Ps: 1) If any one have a better solution please let me know. 2) Sorry for my english, i'm using google translate.

Converting MySQL query into JPA to get count

Here I'm having a SQL query which is working fine to get count from the MySQL database which is as
#Query("SELECT count(is_accepted) as value, post_type, is_accepted from agent_activities where "
+ "YEAR(created_date_time) as year and post_type = 'ticket' " + "GROUP BY is_accepted")
And when I'm trying into Java as JPA query it's not working.
public interface AgentActivitiesRepo extends JpaRepository<AgentActivitiesEntity, Long> {
#Query("select new ProductIssuesModel"
+ "(count(data.isAccepted) as acceptCount) "
+ "from data where YEAR(data.createdDate) as :year "
+ "and data.postType = :postType " + "group by data.isAccepted")
public List<ProductIssuesModel> findAgentActivitiesYearly(Long year, String postType);
}
Here ProductIssuesModel is like:
public class ProductIssuesModel {
private Long acceptCount;
private Long rejectCount;
private Long year;
private Long month;
...}
By running above query, I face an error as:
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: as near line 1, column 137 [select new com.accenture.icoe.fm.model.ProductIssuesModel(count(data.isAccepted) as acceptCount) from data where YEAR(data.createdDate) as :year and data.postType = :postType group by data.isAccepted]
Please let me know if you see any error.
There are two ways to write a JPQL -
Indexed Query Parameters
#Query("select new ProductIssuesModel"
+ "(count(data.isAccepted) as acceptCount) "
+ "from data where YEAR(data.createdDate) = ?1 "
+ "and data.postType = ?2 " + "group by data.isAccepted")
public List<ProductIssuesModel> findAgentActivitiesYearly(Long year, String postType);
The values of the parameters will be bind to the query based on the position/index.
Named Parameters
#Query("select new ProductIssuesModel"
+ "(count(data.isAccepted) as acceptCount) "
+ "from data where YEAR(data.createdDate) = :year "
+ "and data.postType = :postType " + "group by data.isAccepted")
public List<ProductIssuesModel> findAgentActivitiesYearly(#Param("year") Long year, #Param("postType") String postType);
In your case, the second approach is applicable.
Here , YEAR(data.createdDate) as :year is not a condtional expression.
You may be try to do this YEAR(data.createdDate) = :year.
And use #Param to use parameter in JPQL
#Query("select new ProductIssuesModel"
+ "(count(data.isAccepted) as acceptCount) "
+ "from data where YEAR(data.createdDate) = :year "
+ "and data.postType = :postType " + "group by data.isAccepted")
public List<ProductIssuesModel> findAgentActivitiesYearly(#Param("year") Long year, #Param("postType") String postType);

Unable to fetch all where userRole = "ManagerRole" from users table

This is my entity class.
#NamedQueries({ #NamedQuery(name = UsersEntity.NAMED_QUERY_SELECT_ALL_BY_MANAGER_ROLE,
query = "SELECT e FROM " + UsersEntity.ENTITY_NAME + " e WHERE e." +
UsersEntity.FIELD_NAME_USER_ROLE + " = '" +
UsersVO.USER_ROLE + "'") })
#Column(name = "USER_ROLE", nullable = false, length = 30)
private String userRole;
public static final String FIELD_NAME_USER_ROLE = "userRole";
This is the java class from where i execute query
#GET
#Path("/userrole")
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public UsersListVO getUsers(#QueryParam("userRole") String userRole) {
// public UsersListVO getUsers(){
System.out.println(">>>>>here");
UsersListVO usersListVO = new UsersListVO();
try {
List<UsersEntity> usersEntityList = em.createNamedQuery(UsersEntity.NAMED_QUERY_SELECT_ALL_BY_MANAGER_ROLE, UsersEntity.class).setParameter(UsersEntity.FIELD_NAME_USER_ROLE, userRole).getResultList();
The test case is :-
#Test
public void testGetUsers() {
System.out.println("Start test ");
UsersListVO usersListVO = baseWebTarget.path("userrole").queryParam("userRole", "AppSystemManagerUserRole").request(MediaType.APPLICATION_JSON).get(UsersListVO.class);
if (usersListVO.getStatusType().equals(StatusTypeVO.FAILURE)) {
Assert.fail(usersListVO.getMessage());
} else {
System.out.println(usersListVO.getMessage());
}
}
I want to fetch all the managers whose roles are managerRole from users table.But got error while executing the test case in to my jdeveloper. The error i got is
java.lang.AssertionError: You have attempted to set a parameter value
using a name of userRole that does not exist in the query string
SELECT e FROM UsersEntity e WHERE e.userRole =
'AppSystemManagerUserRole'.
The error
java.lang.AssertionError: You have attempted to set a parameter value using a name of userRole that does not exist in the query string SELECT e FROM UsersEntity e WHERE e.userRole = 'AppSystemManagerUserRole' is indicating the you are trying to set a parameter that doesn't exist in your named query.
Your named query:
query = "SELECT e FROM " + UsersEntity.ENTITY_NAME + " e WHERE e." +
UsersEntity.FIELD_NAME_USER_ROLE + " = '" + UsersVO.USER_ROLE + "'"
after string concatenation results in:
query = "SELECT e FROM UsersEntity e WHERE e.userRole = 'AppSystemManagerUserRole'"
As you can see there is not named parameter that you can set. And when you tried calling setParameter(UsersEntity.FIELD_NAME_USER_ROLE, userRole) it threw the exception.
You need to introduce named parameter as below in your named query that you allows you to set later in your code.
query = "SELECT e FROM " + UsersEntity.ENTITY_NAME + " e WHERE e." +
UsersEntity.FIELD_NAME_USER_ROLE + " = :" + UsersEntity.FIELD_NAME_USER_ROLE
would result in the
query = "SELECT e FROM UsersEntity e WHERE e.userRole = :userRole"
With this you should be able to set the parameter and should work.

List is not being initialize when using NEW in JPQL

I have a rather simple query that takes input for a few tables. When I try and run the query it says:
[ERROR] org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].
[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in
context with path [] threw exception [Request processing failed; nested
exception is org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.QueryException: could not instantiate class
[com.htd.domain.ShopOrder] from tuple; nested exception is
java.lang.IllegalArgumentException: org.hibernate.QueryException: could not
instantiate class [com.htd.domain.ShopOrder] from tuple] with root cause
java.lang.IllegalArgumentException: null
JPQL query:
#Query("SELECT NEW com.htd.domain.ShopOrder(po.id, po.po_number, "
+ "po.due_date, po_part.id, po_part.part_quantity, "
+ "part.id, part.part_number, part.part_description, "
+ "part.plasma_hrs_per_part, part.grind_hrs_per_part, "
+ "part.mill_hrs_per_part, part.brakepress_hrs_per_part) "
+ "FROM Po po "
+ "LEFT JOIN po.partList po_part "
+ "LEFT JOIN po_part.part part "
+ "LEFT JOIN po_part.part where po.id = ?1")
List<ShopOrder> getShopOrder(Long id);
ShopOrder.java
public ShopOrder(long po_id, String po_number, LocalDate po_due_date,
long po_part_id, int part_quantity, long part_id,
String part_number, String part_decription, BigDecimal plasma_hrs,
BigDecimal grind_hours, BigDecimal mill_hrs,
BigDecimal breakpress_hrs) {
this.po_id = po_id;
this.po_number = po_number;
this.po_due_date = po_due_date;
this.po_part_id = po_part_id;
this.part_quantity = part_quantity;
this.part_id = part_id;
this.part_number = part_number;
this.part_decription = part_decription;
this.plasma_hrs = plasma_hrs;
this.grind_hours = grind_hours;
this.mill_hrs = mill_hrs;
this.breakpress_hrs = breakpress_hrs;
}
I created a Juint test to see what was going on by doing the following:
#Test
#Transactional
public void shopOrderTest() throws Exception
{
Po po = new Po();
Long id = (long) 11;
LocalDate date = new LocalDate(2015,6,10);
po.setDue_date(date);
po.setId(id);
po.setPo_number("11254");
po.setSales_order_number("34879");
po.setStatus("ordered");
BigDecimal total_sale = new BigDecimal("55");
po.setTotal_sale(total_sale);
Part part = new Part();
BigDecimal brakepress_hrs_per_part = new BigDecimal("34");
part.setBrakepress_hrs_per_part(brakepress_hrs_per_part);
BigDecimal grind_hrs_per_part = new BigDecimal("354");
part.setGrind_hrs_per_part(grind_hrs_per_part);
part.setId(id);
part.setInventory_count(55);
BigDecimal laser_hrs_per_part = new BigDecimal("987");
part.setLaser_hrs_per_part(laser_hrs_per_part);
BigDecimal lb_per_part = new BigDecimal("58748");
part.setLb_per_part(lb_per_part);
poRes.save(po);
partRes.save(part);
List<ShopOrder> getOrders = po_partRepository.getShopOrder(id);
int size = getOrders.size();
System.out.println("The size is-----"+size);
for(ShopOrder order: getOrders){
System.out.println(order);
}
}
}
Now the test passes but the size of the List is 0 which explains why I am getting a null error. However I do not understand why.
The method that is giving me the null error is here:
/**
* Generate Shop Orders.
*/
#SuppressWarnings("null")
#RequestMapping(value = "/generateShopOrder/{id}", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public void generate(#PathVariable Long id) throws URISyntaxException {
System.out.println("po id to generate = " + id);
List<ShopOrder> shopOrders = po_partRepository.getShopOrder(id);
for(ShopOrder<?> order: shopOrders) {
System.out.println("-------Printing Shop Orders" + order);
}
}
Po.java
#OneToMany(mappedBy="po",targetEntity=Po_part.class)
private List<Po_part> partList;
public List<Po_part> getPartList() {
return partList;
}
Part.java
#OneToMany(mappedBy="part",targetEntity=Po_part.class)
private List<Po_part> partList;
Po_part.java
#ManyToOne
private Part part;
#ManyToOne
private Po po;
I hope this clears things up with my query. If you have any suggestions on how I should do a better query I am all ears.
Here is a picture of my database tables too:
#Query("SELECT NEW com.htd.domain.ShopOrder(pp.po.id, pp.po.po_number, pp.po.due_date, pp.id, pp.part_quantity, "
+ "pp.part.id, pp.part.part_number, pp.part.part_description, pp.part.plasma_hrs_per_part, pp.part.grind_hrs_per_part, "
+ "pp.part.mill_hrs_per_part, pp/part.brakepress_hrs_per_part) "
+ "FROM Po_part pp Where pp.part.id = ?1")
List<ShopOrder> getShopOrder(Long id);
without join
#Query("SELECT NEW com.htd.domain.ShopOrder(po.id, po.po_number, po.due_date, po_part.id, po_part.part_quantity, "
+ "part.id, part.part_number, part.part_description, part.plasma_hrs_per_part, part.grind_hrs_per_part, "
+ "part.mill_hrs_per_part, part.brakepress_hrs_per_part) "
+ "FROM Po po "
+ "LEFT JOIN Po_part po_part ON po_part.po.id = po.id"
+ "LEFT JOIN Part part ON po_part.part.id = part.id AND po.part.id = ?1")
List<ShopOrder> getShopOrder(Long id);
with Left join

Categories

Resources