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).
Related
I have a many to many relationship in spring boot with User and Role. I have three tables in database (Role_utilisateur, users_roles and utilisateurs). In my repository, ireturn List of my entite called RoleEntite which have two attributes (nom and id).
#Query(value = "SELECT ROLE_UTILISATEUR.NOM, ROLE_UTILISATEUR.ROLE_ID " + "FROM ROLE_UTILISATEUR "
+ "INNER JOIN USERS_ROLES on users_roles.role_id = ROLE_UTILISATEUR.ROLE_ID "
+ "INNER JOIN UTILISATEURS on utilisateurs.utilisateur_id = USERS_ROLES.UTILISATEUR_ID "
+ "WHERE UTILISATEURS.UTILISATEUR_ID = :userId", nativeQuery = true)
List<RoleEntite> findUsersRolesNative(#Param("userId") Long userId);
When i call my function in
private List<GrantedAuthority> getGrantedAuthorities(UserEntite user) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
List<RoleEntite> roleList = userRepository.findUsersRolesNative(user.getId());
for (RoleEntite roleEntite : roleList) {
authorities.add(new SimpleGrantedAuthority(roleEntite.getNom()));
}
return authorities;
}
I get this error in my java eclipse
org.springframework.security.authentication.InternalAuthenticationServiceException: Failed to convert from type [java.lang.Object[]] to type [com.id.firstSpringBoot.entite.RoleEntite] for value '{ADMIN, 1}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [com.id.firstSpringBoot.entite.RoleEntite]
How can i resolve this error and get the name ADMIN in my function getGrantedAuthorities can do this
The problem is you're selecting two columns and returning a list of entities. You need to either select the entity in your query or return the list of two values in a collection.
To return entities you would need to convert your query to JPQL. The following is a JPQL representation of your native query.
I've had to do some guessing for the joins (I assume you have some JPA related entities):
#Query(value = "SELECT RoleEntite r "
+ "INNER JOIN UserRole r.user u "
+ "INNER JOIN Utilisateurs u.Utilisateur x "
+ "WHERE x.UTILISATEUR_ID = :userId")
List<RoleEntite> findUsersRolesNative(#Param("userId") Long userId);
If you go the native query route:
#Query(value = "SELECT ROLE_UTILISATEUR.NOM, ROLE_UTILISATEUR.ROLE_ID " + "FROM ROLE_UTILISATEUR "
+ "INNER JOIN USERS_ROLES on users_roles.role_id = ROLE_UTILISATEUR.ROLE_ID "
+ "INNER JOIN UTILISATEURS on utilisateurs.utilisateur_id = USERS_ROLES.UTILISATEUR_ID "
+ "WHERE UTILISATEURS.UTILISATEUR_ID = :userId", nativeQuery = true)
List<Object[]> findUsersRolesNative(#Param("userId") Long userId);
The returned list should yield:
for (Object[] obj : list) {
nom = obj[0];
roleId = obj[1];
// ... do what ever you want with the values
}
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.
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
I m trying to retrieve values from various tables through my query which is as follows,
select f.* from
(select d.DateKey as DK from dbo.DimDate d where d.date between '01/01/2012' and '07/31/2014' ) m
inner join
(select a. SiteID,a.DateKey,a.Imp,a.OnTarget_Imp,a.Viewable_Imp,b.Plcmnt_Nm from dbo.SocMet_Niel_Fact a left join dbo.SocMet_NielPlcmnt_Dim b on a.PlcmntID = b.PlcmntID) f
on
f.DateKey = m.DK where f.SiteID = '25674897'
This code runs fine in my SQL Server management Studio but when i run it through my java code it isnt working the same way and throws the Arithmetic overflow Error..
My servlet code for handling this query is
if(type.equals("paid_placement"))
{
try
{
System.out.println("I m in Paid Placement");
String site=request.getParameter("site_id");
System.out.println(site);
int sid=Integer.parseInt(site);
System.out.println(sid);
String start_date=request.getParameter("s_date");
String end_date=request.getParameter("e_date");
prepStmt = con.prepareStatement(dbquery.pdd_placement);
prepStmt.setString(2, start_date);
prepStmt.setString(3, end_date);
prepStmt.setInt(1, sid);
rs = prepStmt.executeQuery();
place_array = new JSONArray();
while(rs.next())
{
json=new JSONObject();
json.put("placement_name", rs.getString("Plcmnt_Nm"));
json.put("impressions", rs.getString("Imp"));
json.put("ontarimp",rs.getString("OnTarget_Imp"));
json.put("viewable_imp", (int)rs.getInt("Viewable_Imp"));
place_array.put(json);
}
System.out.println(place_array);
mainjson=new JSONObject();
mainjson.put("paid_placement", place_array);
System.out.println(place_array);
String responsetojsp=mainjson.toString();
System.out.println(responsetojsp);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(responsetojsp);
}
catch(NumberFormatException | SQLException | JSONException | IOException e)
{
logger.error("Error : " + e);
}
}
and the query in the dbquery page looks like this,
public static String pdd_placement = "select f.* from \n" +
" (select d.DateKey as DK from dbo.DimDate d where d.date between ? and ? ) m\n" +
" \n" +
"inner join \n" +
"(select a. SiteID,a.DateKey,a.Imp, a.OnTarget_Imp,a.Viewable_Imp,b.Plcmnt_Nm from dbo.SocMet_Niel_Fact a left join dbo.SocMet_NielPlcmnt_Dim b on a.PlcmntID = b.PlcmntID) f \n" +
" on \n" +
" f.DateKey = m.DK where f.SiteID = ?";
After few comments in this question i have updated my code a little bit i have actually converted my string date values into sql.date values as follows
Date s_date;
s_date = (Date) formatter1.parse(start_date);
Date e_date;
e_date = (Date) formatter1.parse(end_date);
java.sql.Date sqlS_Date;
sqlS_Date = new java.sql.Date(s_date.getTime());
java.sql.Date sqlE_Date;
sqlE_Date = new java.sql.Date(e_date.getTime());
but still it throws an error,
java.util.Date cannot be cast to java.sql.Date
can someone help me with this??
I have 3 queries:
// (1)
String sql = "SELECT tblClientInfo.ClientID, tblrefmarket.MarketDesc, tblclientinfo.LastName, tblledger.LoanAmount, "
+ "tblledger.DateStarted, tblledger.DailyPay, tblledger.Expiry FROM tblclientinfo Inner Join tblbusinessinfo ON tblbusinessinfo.ClientID = tblclientinfo.ClientID "
+ "Inner Join tblrefmarket ON tblbusinessinfo.MarketID = tblrefmarket.MarketID "
+ "Inner Join tblledger ON tblledger.ClientID = tblclientinfo.ClientID where MarketDesc = ?";
// (2)
String sumSQL = "SELECT ClientID, sum(tblloanpayment.AmountPaid) as sum FROM tblloanpayment where tblloanpayment.ClientID= ? ";
// (3)
String balSQL = "SELECT (SELECT tblLedger.LoanAmount from tblLedger WHERE tblLedger.ClientID = ?) - (SELECT SUM(tblLoanPayment.AmountPaid) "
+ "FROM tblLoanPayment WHERE tblLoanPayment.ClientID = ?) as balance FROM dual; ";
I have executed this 3 queries to display informations on a jTable. And it was successful.
Now my problem is when I am generating the report (or print) using JasperReports.
I can only display the 1st query since it is inside the database. While query 2 and 3 are not. They are just computations of the payments made in query 1.
How can I join this so that I can be able to display all necessary informations?
Here's my code:
private void cmdPrintActionPerformed(java.awt.event.ActionEvent evt) {
int row = tableMarket.getSelectedRow();
try {
JasperDesign jasperDesign = JRXmlLoader.load("notes receivables.jrxml");
String sql = "SELECT tblClientInfo.ClientID, tblrefmarket.MarketDesc, tblclientinfo.LastName, tblledger.LoanAmount, "
+ "tblledger.DateStarted, tblledger.DailyPay, tblledger.Expiry FROM tblclientinfo Inner Join tblbusinessinfo ON tblbusinessinfo.ClientID = tblclientinfo.ClientID "
+ "Inner Join tblrefmarket ON tblbusinessinfo.MarketID = tblrefmarket.MarketID "
+ "Inner Join tblledger ON tblledger.ClientID = tblclientinfo.ClientID where MarketDesc = '" + tableMarket.getModel().getValueAt(row, 0).toString() + "'";
JRDesignQuery newQuery = new JRDesignQuery();
newQuery.setText(sql);
jasperDesign.setQuery(newQuery);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, null, conn);
JasperViewer.viewReport(jasperPrint);
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, e);
}
}
This code displays only the first query.
You are already selecting tblLedger.LoanAmount in your first query, so the only additional information required from both your second and third queries is sum(tblloanpayment.AmountPaid). Try:
SELECT c.ClientID,
m.MarketDesc,
c.LastName,
l.LoanAmount,
l.DateStarted,
l.DailyPay,
l.Expiry,
s.sumPaid,
l.LoanAmount - s.sumPaid as balance
FROM tblclientinfo c
Inner Join tblbusinessinfo b ON b.ClientID = c.ClientID
Inner Join tblrefmarket m ON b.MarketID = m.MarketID
Inner Join tblledger l ON l.ClientID = c.ClientID
left join (SELECT ClientID, sum(AmountPaid) as sumPaid
FROM tblloanpayment group by ClientID) s on c.ClientID = s.ClientID
where m.MarketDesc = ?
Remove the restriction by client id in the second and third queries. Make them into subselects (that is, put them in parentheses) and make a big select that joins all three subselects on client id.
Edit
So if the three queries are query1, query2, query3, you'd end up with
select ... from (query1) baseSql
join (query2) sumSql on baseSql.clientId = sumSql.clientId
join (query3) balSql on baseSql.clientId = balSql.clientId
You may need to use left join instead of join if there are rows in baseSql that are missing from sumSql or balSql.