Parameters are not getting subsituted in MyBatis query - java

The following is my select query in BrandMapper.xml.
<select id="getBrand" parameterType="String" resultMap="brandResult">
SELECT
B.bid as bid,
B.bname as bname,
B.avg_price as avg_price,
B.total_number as total_number,
P.pid as pid,
P.pname as pname,
P.bid as pbid,
P.bname as pbname,
P.specs as pspecs,
P.price as price
from Brands B left outer join Products P on P.bid = B.bid
where B.bname = #{bname, jdbcType=VARCHAR}
</select>
This is the interface
public interface BrandMapper {
BrandDAO getBrand(String bname);
}
This is the service class
#Service
public class BrandService {
#Autowired
private BrandMapper brandMapper;
public BrandDAO getBrand(String bname) {
System.out.println("Inside DBService getBrand");
return brandMapper.getBrand(bname);
}
}
My problem is that the getBrand function in BrandService returns a null value. If I replace the parameter #{bname} inside the BrandMapper.xml by a hardcoded string it works and returns the correct class. What am I doing wrong here? Is there any logs or anything available where I can see the actual query which is being constructed? Any help is appreciated.
I managed to enable loggin using log4j and this is the query which is getting executed
SELECT B.bid as bid, B.bname as bname, B.avg_price as avg_price, B.total_number as total_number, P.pid as pid, P.pname as pname, P.bid as pbid, P.bname as pbname, P.specs as pspecs, P.price as price from Brands B left outer join Products P on P.bid = B.bid where B.bname = ?
The parameter is not getting replaced. I cant figure out what I am doing wrong here.

The question mark is a placeholder in Prepared Statements, the logged query is perfectly fine and looks as expected. The real value should be passed along the query to your database as a separate parameter.

Related

Sql query call fails if no record is found

I am trying to fetch a string from sql db. I have the following query:
select DISTINCT HARDWARE.NAME
from HARDWARE INNER JOIN
HARDWARE_LINKING
on HARDWARE.ID = HARDWARE_LINKING.ID
where HARDWARE_LINKING.EXTERNALID='5528752'.
Now when there is no record against any id the function call fails.
here is my function code that I am calling to fetch data:
public String search(String externalId) {
String SQL = "select DISTINCT HARDWARE.NAME from HARDWARE INNER JOIN HARDWARE_LINKING on HARDWARE.ID = HARDWARE_LINKING.ID where HARDWARE_LINKING.EXTERNALID=?";
Object[] input = new Object[] {externalId};
String name = jdbcTemplate.queryForObject(SQL,input, String.class);
return name;
}
Is there any way I can return a default value? and sometimes there are multiple values return but I want only single string value to be returned, Is that possible? Thankyou in advance
One method is to put the default into the query itself. Use an aggregation function and COALESCE():
select coalesce(h.NAME, '<default value>') as NAME
from HARDWARE h INNER JOIN
HARDWARE_LINKING hl
on h.ID = hl.ID
where hl.EXTERNALID = '5528752';
An aggregation query with no GROUP BY always returns one row, so this would seem to be more what you are looking for.
Also note that I put table aliases into the query. These make the query easier to write and to read.
You should be able to check name for null or isEmpty and then decide if you should return the name from the query or a default value.
if(name != null && !name.isEmpty()){
return name;
} else {
return "default";
}

How can I find a value in a table via an another related value in that table?

I created a table in a Database, so I got a "customerId" in that table and a "cardId", so a Customer can has multiples cardId's . What I tried right now is that:
public CustomerId getCustomerId(String cardId) {
this.getEntityManager();
return em.find(CustomerMappingHelper.class, customerId);
}
even though this won't work (I guess since my Ecplise shows me some Errors) ......furthermore I have in an another class a lookup methode, right now I stuck because I'm not sure how I can look up after a customer Id through an another card Id, just the logic behind that to look in that row ?
Used JPQL and solved my Problem, here I search the customerId through the cardId
public String getCustomerId(String cardId) {
Query q = em.createQuery("SELECT c.customerId FROM CustomerMapping c WHERE c.cardId = :cardId");
q.setParameter("cardId", cardId);
String customerId = (String) q.getSingleResult();
return customerId;

how to get only selected table from stored procedures?

I have a stored Procedure like the following
CREATE PROCEDURE [dbo].[spConfiguration_test]
#ID int
AS
select empid,name from employee;
select * from address;
I wanted to call this stored procedure from jpa.So I did like this
DAOcode
public List test()
{
String execProce="exec spConfiguration_test 1";
System.out.println(execProce);
Query query = entityManagerUtil.entityManager.createNativeQuery(execProce);
return query.getResultList();
}
service class Code
List test=serviceDaoImpl.test();
when I debug this then List(test) size is showing 1 and when I run it then it gives me only the records of 1st table(select empid,name from employee;)
But I want the details of 2nd table when the stored procedure is executed.
Can any one guide me please?
If you merge the two queries into one. Then everything must work.
Example:
SELECT e.empid
,e.name
,a.*
FROM employee e
,address a
WHERE e.empid = a.empid;

order by when using Constructor Expressions in JPA 2

As a part of JSR-338 came the feature of using Constructor Expressions.
The question is how I can use order by when using Constructor Expressions.
Given the example JPQL:
select com.acme.AggregatedInfo(
c,
(select status from Account where ssn = c.ssn)
)
from Customer c
where m.id in (:customerIdList)
And the class AggregatedInfo
class AggregatedInfo {
private final Customer customer;
private final String status;
public AggregatedInfo(Customer customer, String status) {...}
// boilerplate javacode....
}
Im using this from a DAO like this:
public List<AggregatedInfo> getAggregatedResult(final List<Long> customerIdList)
return em.createQuery(hql, AggregatedInfo.class)
.setParameters("customerIdList", customerIdList)
.getResultList();
}
If I want to order by the status - how can this be done via JPQL ?
I have tried the following without success:
select com.acme.AggregatedInfo(
c,
(select status from Account where ssn = c.ssn)
) as a
from Customers c
where m.id in (:customerIdList)
order by c.status
But this does not work.
Is it doable ?
Please explain.
Try the following. It worked for me with the similar implementation in Hibernate. It should work for you too
public List<AggregatedInfo> getAggregatedResult(final List<Long> customerIdList)
return em.createNativeQuery(hql, AggregatedInfo.class)
.setParameters("customerIdList", customerIdList)
.getResultList();
}
Replace entityManager.createQuery() with entityManager.createNativeQuery()

Dynamic Hibernate Query

I have a method that I use to return a dynamic query. This method is shown below
public Query getLastId(String sProvider)
{
String serviceProvider = sProvider.toLowerCase();
String query2 = "SELECT MAX(:serviceProvider.id) " +
" FROM :sProvider :serviceProvider ";
return em.createQuery(query2)
.setParameter("sProvider", sProvider)
.setParameter("serviceProvider", serviceProvider);
}
I want this method to return this
SELECT MAX(multichoice.id) FROM Multichoice multichoice
when I call the method like this
getLastId("Multichoice");
Please how do I write the query variable to return the answer?
To do this task you can use Criteria object model and projections to run your query over different types:
Take a look at this article (15.7. Projections, aggregation and grouping)
here is the code :
List results = session.createCriteria(class)
.setProjection( Projections.max("id"))
.list();
Then instead of a string you should send a class to your method.

Categories