How to use POJO properties in orm.xml for Named Native Query - spring

I am fairly new to using JPA/HIbernate and the orm.xml way of doing named native queries. I can't seem to figure out how to pass an object as a parameter to my orm.xml file.
I have a method:
#Query(nativeQuery = true)
POJO selectPOJO(#Param("pojo") POJO pojo);
and in my orm I am trying to reference some of the properties in that pojo object:
<query>
SELECT * FROM table
WHERE id = :pojo.getId
AND name = :pojo.getName
</query>
I have simplified my actual expression in the examples above, however when I run the code I get an error:
java.lang.IllegalArgumentException: Could not locate named parameter [pojo], expecting one of [pojo.getId, pojo.getName]
If anyone knows how to pass through a POJO/Object and use that objects fields in the orm.xml or if anyone could point me to the documentation explaining how to do it that would be a huge help.
Thanks!

Related

How does Spring Data JPA resolve property name containing single letter abbreviation for a word in query methods?

I've an entity with property name qYear. I tried creating a findByIdAndQYear method in repository but that did not work. I ran into IllegalArgumentException: Unable to locate Attribute with the the given name [QYear] on this ManagedType).
However findByIdAndqYear works. Any idea how single letter abbreviations like this are expanded please?
Spring Data (not just the JPA module) base this on the Java Bean Specification.
In order to avoid misinterpretation of the specification this is actually implemented using [java.beans.Introspector][1].
See also https://jira.spring.io/browse/DATACMNS-1589

Spring data jpa, externalizing native queries

I am using Spring data jpa for executing native Query, here is the example.
#Query(value = "select name from customer", nativeQuery = true)
public List<String> findNameNative() ;
Now, due to company constraint can't put the entire query here, but query is pretty huge, like 100 lines.
N we have many such queries.
Is there a way i can define queries in a separate file like xml or properties file and refer them here. (to keep the code clean)
Appericiate the help.
Thanks.
After many efforts and tries found the solution.
1) create the xml file (with any name) in resources folder of your project. Say testSQL.xml inside resources /query
2) follow the xml standard of 'orm.xml' in testSQL.xml, this copy paste the header and create the tags of,
<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
version="1.0">
<named-native-query>
</named-native-query>
</entity-mapping>
3) in this xml create the tag with named-native-query tag.
<named-native-query name="XyzEntity.methodName">
<query>
<! [CDATA[
Your native query
] ] >
</query>
</named-native-query>
Note - > multiple such native named query tags can be added and all of them must reside between
<entity-mapping> </entity-mapping>
4) "XyzEntity" mentioned in name tag in above step, should have a Jpa repository and in that repository we should have method with the same name as the tag. I. E.
public interface XyzRepo extends JpaRepository <XyzEntity, Long> {
Tuple methodName() ;
}
5) add the testSQL.xml in application property file as below
spring.jpa.mapping-resources = query/testSQL.xml
N then you can call this method normal spring way.
Kindly let me know if someone is stuck on this and need detail solution.
You can externalize de value, which is the query itself. Inside the src/main/resources, create a folder called META-INF. Inside it, create a file called jpa-named-queries.properties.
Suppose your entity is called Customer and the table is TBL_CUSTOMER.
When you keep the query inside the code, on your repository, you have the code you wrote. You can externalize it this way:
CustomerRepository.java
#Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
#Query(nativeQuery = true)
public List<String> findNameNative();
}
jpa-named-queries.properties
Customer.findNameNative=\
SELECT C.NAME \
FROM TBL_CUSTOMER C \
WHERE CONDITIONS
Names must match and you must use \ for line breaks.
Under resources create META-INF/jpa-named-queries.properties. In this file define your queries this way:
MyEntity.fetchEntityBySomething=select name from Customer
I have not tried native queries however, usual queries would work this way.
However, check this out: https://github.com/gasparbarancelli/spring-native-query
I think DarkKnight's solution is the best, set entity mappings with xml can take advantage of IDE to have highlight and indentation.
But if you are using spring boot, there will be an optimization.
There is a related spring boot property for it: spring.jpa.mapping-resources, you can set entity mappings path into this property. And this property can be an array, you can set more than one value into it.

Spring Batch - Writing a List<List<>> from Reader to CSV using Flatfilewriter

The Reader we have written uses a DAO to query the database based on some parms and returns a list of Objects List<> . But the FlatFilewrite for some reason fails as its is unable to map the field names . Further debugging I feel that the Write is unable to accept the List or Reader is sending a List> . Please let us know how to handle the same .
org.springframework.beans.NotReadablePropertyException: Invalid property 'costCenter' of bean class [java.util.ArrayList]: Bean property 'costCenter' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
My code is same as the below , xcept the reader is a custom one with a DAO and returns a list .
http://websystique.com/springbatch/spring-batch-read-from-mysql-database-and-write-to-a-csv-file/
You can wrap your FlatFileItemWriter in a delegating writer that unpacks and combines the lists then passes them on. This old answer contains an example that should work.

Java Spring, JPA - like expression with wildcard

I am struggling with creation of JPQL statement using Like expression in Java Spring application. My aim is to implement simple case insensitive search function.
My code, which should return a list of companies containing a keyWord in their name looks like this:
List<Company> companies = em.createQuery("select cmp from JI_COMPANIES as companies where UPPER(cmp.name) LIKE :keyWord", Company.class)
.setParameter("keyWord","%" + keyWord.toUpperCase() + "%").getResultList();
return companies;
However, this query only works when my keyWord matches the name of company (Like statement is not used).
When testing the function above, I see in my console message from Hibernate:
Hibernate: select ... /* all my parameters */ ... where company0_.CMPN_NAME=?
It seems that my query is translated to cmpn_name='name' instead of using like expression.
You can look about Hibernate batch processing best pratices and Stateless session.
It was my fault due to not understanding how Spring Data JPA library works.
I have tried to create a custom implementation of myCompanyRepository (myCompanyRepository extends JpaRepository, CompanyRepositoryCustom).
The code which I mentioned above was located in my CompanyRepositoryCustomImpl class which implements CompanyRepositoryCustom interface. However I used method name "findCompaniesByName(String name)". JPA automatically creates a query from this method name and my implementation is not used.
Here is the link for Spring Data JPA reference

How to get property from context property placeholder tag inside custom java component

I have Mule Configuration that defines
<context:property-placeholder location="classpath:/mule-sw.properties"/>
And I also have a custom component class in Java which use #Lookup annotation on one of my field
#Lookup("file-path")
private String path;
Considering my "mule-sw.properties" is like this
file-path=C:/hello.txt
After I start up the Mule App, I always get Deploy Exception
org.mule.api.expression.RequiredValueException: "Required object not found in registry of Type "class java.lang.String" with name "file-path" on object "class component.CustomComponent"
I also tried to change the #Lookup("file-path") with #Lookup("${file-path}") with no success.
Anyone can give me a better solution ?
Any help is kindly appreciated.
Thanks
The #Lookup annotation is designed to retrieve objects from the registry , whereas what you are trying to do is to assign a value to an attribute of your custom component.
There are 2 way to do that:
1) Through property injection, i.e. you declare your component like the following:
<custom-component class="org.myCompany.CustomComponent">
<property name="file-path" value="${file-path}" />
</custom-component>
2) Through Spring EL support and the #Value annotation, i.e. you annotate your attribute in the following way
#Value("${file-path}")
private String path;
I'd recommend the first approach since it is easier to maintain from a flow perspective
#Value("#{'${file-path}'}")
private String path;
Give this a shot. I think you need to wrap it in an EL block #{} for it to be properly recognized.

Resources