List is not being initialize when using NEW in JPQL - java

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

Related

Spring JdbcTemplate select alias table column

JdbcTransfersDao.java:
//row mapper
private TransfersHistory mapRowsToTransfersHistory(SqlRowSet rowset){
TransfersHistory newTransfersHistory = new TransfersHistory();
newTransfersHistory.setTransferId(rowset.getInt("transfer_id"));
newTransfersHistory.setToFrom(rowset.getString("to_from"));
newTransfersHistory.setAmount(rowset.getBigDecimal("amount"));
return newTransfersHistory;
}
public TransfersHistory[] transfersHistoryByUserId(int loggedInUser){
String sqlTransfersHistory = "select t.transfer_id, 'to: '||(select username from users as fu join accounts fa on fu.user_id = fa.user_id where account_id = t.account_from) as to_from, t.amount from transfers as t" +
" where" +
" t.account_to = (select account_id from accounts as ta join users tu on ta.user_id = tu.user_id where tu.user_id= ?)" +
" union" +
" select t.transfer_id, 'from: '||(select username from users as fu join accounts fa on fu.user_id = fa.user_id where account_id = t.account_to) as to_from, t.amount from transfers as t" +
" where" +
" t.account_from = (select account_id from accounts as ta join users tu on ta.user_id = tu.user_id where tu.user_id= ?);";
SqlRowSet rs = jdbcTemplate.queryForRowSet(sqlTransfersHistory, loggedInUser);
rs.getMetaData();
List<TransfersHistory> tempTransfersHistory = new ArrayList<>();
while (rs.next()){
tempTransfersHistory.add(mapRowsToTransfersHistory(rs));
}
TransfersHistory[] tempTransferHistoryArr = new TransfersHistory[tempTransfersHistory.size()];
tempTransfersHistory.toArray(tempTransferHistoryArr);
return tempTransferHistoryArr;
}
Controller.java
public List<TransfersHistory> transfersHistory(String base_url, AuthenticatedUser authenticatedUser){
HttpHeaders headers = setupAuth(authenticatedUser);
HttpEntity<?> entity = new HttpEntity<>(headers);
ResponseEntity<TransfersHistory[]> res = restTemplate.exchange(base_url + transfers_history_resource, HttpMethod.POST, entity, TransfersHistory[].class);
List<TransfersHistory> tempTransfers = new ArrayList<>();
tempTransfers = Arrays.asList(res.getBody());
return tempTransfers;
}
TransfersHistory.java
public class TransfersHistory {
private int transferId;
private String toFrom;
private BigDecimal amount;
}
Why is this returning error: "PreparedStatementCallback; SQL [select t.transfer_id, 'to:'||(select username from users as fu join..."? Is it because of nested Select statements?
to_from: is "alias column"
Figured it out.
Looks like .queryForRowSet() and .queryForObject() does not like SQL union operator so I had to use myPreparedStatement.executeQuery(mySql).

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);

Table is not Mapped In HQL query

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";

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.

Categories

Resources