Java Spring, JPA - like expression with wildcard - spring

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

Related

Spring data JPA Checkmarx vulnerability- Improper Resource Access Authorization for #Query annotation

We are currently working on web application with persistence layer implemented using Spring data JPA and its working out really well for us however while scanning our code using checkmarx it complains for "Improper Resource Access Authorization" error for all input parameter in below code snippet.Not sure how to resolve it.Based of my understanding we tried following approach but that didn't help either
Whitelist input parameter using using #valid and #Pattern
annotations
Secure method using #Secured("ROLE_TEST") annotation of spring security.
#Repository
public interface EmployeeAddressRepository extends JpaRepository<EmployeeAddress, Integer> {
#Query("select empAdd from EmployeeAddress empAdd where empAdd.Employee.employeeId=?1 and (endDate) ORDER BY empAdd.lastUpdateTimeStamp DESC")
List<EmployeeAddress> findEmployeeAddressByEmployeeId(String employeeId, LocalDate date) throws PersistenceException;
}
Looking forward for any pointer here to move forward in right direction
In the comments for one of the other answers someone provided the answer. Essentially Checkmarx is unable to determine if you are checking if the user/service has permission to execute this command.
A secure implementation would look like:
if(userCanPerformAction(employeeId)){
repository.findEmployeeAddressByEmployeeId(employeeId, date)
}
It's not smart enough to know if your code prior to the call to the repository has actually performed the checks needed. So, what you have to do is verify that you are doing the correct validation checks before executing findEmployeeAddressByEmployeeId. If you are, then you would follow your organizations process for marking something as a false positive.
Perhaps Checkmarx doesn't support ordinal parameters notation, try rewriting the query like so:
#Query("select empAdd from EmployeeAddress empAdd where empAdd.Employee.employeeId= :empId and (endDate) ORDER BY empAdd.lastUpdateTimeStamp DESC", employeeIdParameter)
where employeeIdParameter is the input parameter.
Hope this helps,
Amit

IgnoreCase Finder Not Working with Spring Data Rest and Neo4J

I am unable to coax Spring Data Neo4J (with Spring Data Rest) to ignore case with a finder method. Here's an example repository:
#RepositoryRestResource
public interface WidgetRepository extends PagingAndSortingRepository<Widget, Long> {
Optional<Widget> findByNameIgnoreCase(String name);
}
This example will only find widgets by exact case even though I have the IgnoreCase keyword. I would appreciate advice on how to get a finder method to ignore case with Neo4J. Thanks!
The case specific keywords are not implemented in Spring Data Neo4j yet. But it is possible to use regex in a derived query method.
Define a regex finder method
Optional<Widget> findByNameMatchesRegex(String name);
and use it like this
widgetRepository.findByNameMatchesRegex("(?i)paul");
This is the only option right now within Neo4j to find strings by case-insensitive queries. https://neo4j.com/docs/developer-manual/current/cypher/clauses/where/#case-insensitive-regular-expressions
However this might be useful to support the ignoreCase keyword within Spring Data Neo4j as a convenient access function.

Spring JPA derived delete query

I am using Spring Data rest with Spring JPA. I have one Spring JPA derived delete query that should deletes the list of items but when I am executing it and noticing the console I found that it is executing select query instead that's very strange situation I have ever come across.
#RepositoryRestResource(collectionResourceRel="revision", path="revision")
interface RevisionRepository extends JpaRepository<Revision, Long> {
List<Revision> deleteByContentId(long contentId)
}
I have even tried using Long instead of List<Revision> doesn't work and also have tried removeByContentId it is also doesn't work either and keeps executing the select query instead delete query.
when I am running this method this is what I got on my console
Hibernate: select revision0_.id as id1_2_, revision0_.body as body2_2_, revision0_.content_id as content_3_2_, revision0_.content_type as content_4_2_, revision0_.date_created as date_cre5_2_, revision0_.file_name as file_nam6_2_, revision0_.folder_id as folder_i7_2_, revision0_.force_ssl as force_ss8_2_, revision0_.is_active as is_activ9_2_, revision0_.lookup as lookup10_2_, revision0_.meta_description as meta_de11_2_, revision0_.meta_keywords as meta_ke12_2_, revision0_.meta_title as meta_ti13_2_, revision0_.nav_item as nav_ite14_2_, revision0_.nav_order as nav_ord15_2_, revision0_.regions_objects as regions16_2_, revision0_.summary as summary17_2_, revision0_.title as title18_2_, revision0_.updated_by as updated19_2_, revision0_.user_id as user_id20_2_ from revisions revision0_ where revision0_.content_id=?
does anyone having any idea why it is behaving strangely?
You need to add #Modifying annotation to your delete method. You will also need to make sure it is executed within a transaction, so you might need to add #Transactional annotation too, if you invoke this method not in a transaction.
Please see an example:
#Modifying
#Transactional
int deleteByFieldName( Long fieldValue );
In latest Spring >=5 and Spring Boot >=2.
#Transactional
int deleteByFieldname( Long fieldValue );
Works fine.
Note 1:
#Modifiyng annotation has absolutely no effect in this. It only work for #Query annotation. Without #Query, it is simply ignored.
Note 2:
In naming convention, that depends on the configured NamingStrategy, the CamelCase might be interpreted and nested entity relation or "_" in field name. So "Fieldname" and "FieldName" mean very different things.
Note 3:
Derived delete queries like this have a really nasty n+1 side effect. They ALWAYS first issue select for the rows then isses delete each row/entity one by one with separate delete stement. No way around this, except using #Query() with manual delete statement. And using #Query then requires the #Modifying for delete query.

spring for mongodb escaping parameters to avoid SQL injection

I am a new-by using spring with MongoDB.
I am using a Dao pattern which uses MongoOperations object.
As I have a lot of experience with RDBMS and JPA usually we use setParameter which also takes care for escaping and avoiding SQL injection.
I am wondering if there is such a think in spring for MongoDB. I could not find it but I might be missing something. I have to say I am still not sure if there is an SQL injection risk using Mongo.
Also, is there a way to create Named Queries in MongoDB?
Thank you all.
There is something very similar to SQL injection which is NOSQL injection.
The special characters are different but the concept is the same : the user can control/modify/corrupt the request.
Yet these databases are still potentially vulnerable to injection attacks, even if they aren't using the traditional SQL syntax. Because these NoSQL injection attacks may execute within a procedural language , rather than in the declarative SQL language, the potential impacts are greater than traditional SQL injection
There is a way to verify, here is an OWASP page that would help you to test.
The basic is to verify that your requests correctly escape ' " \ ; { } and maybe more.
It seems that spring data mongodb correctly escapes those, but I have no idea if it is completely safe.
As for named query, I think this answer is correct and they don't exists but you still have a #Query annotation if you have a repository.
And because you are using a custom repository doesn't mean you can't use a repository interface too, Spring data allows you to have an implementation of the repostiroy without implementing it, see here.
There is no such thing as SQL injection in Mongo, since Mongo does not use SQL language at all.
There is no concept of named queries in Spring Data MongoDB, instead you use annotate your repository methods with #Query:
public interface PersonRepository extends MongoRepository<Person, String>
#Query(value="{ 'firstname' : ?0 }", fields="{ 'firstname' : 1, 'lastname' : 1}")
List<Person> findByThePersonsFirstname(String firstname);
}

Spring-Data + QueryDSL + JDBC: how to map the query results to the domain objects?

I am considering to use Spring-Data + QueryDSL + JDBC to replace (or enhance) the currently used MyBatis.
My reasons are:
Compile-time check of column names
Compile-time check of SQL tatements and auto-completion from IDE
Ability to write unit tests on Java Collections against the same code that will work against the actual DB, which is much simpler and faster than pre-populating a DB
It is more concise than MyBatis – no need for a separate XxxMapper.java and XxxMapper.xml under the DAO layer
Yet I see the following problems:
There is no infrastructure for mapping the query results to domain objects. QueryDSL's QBean and MappingProjection, Spring's BeanPropertyRowMapper and Spring-Data's OneToManyResultSetExtractor seem to be too low level, see below.
No out of the box session/transaction-level cache which comes for free in MyBatis
No out of the box SQL statement and result logging which comes for free in MyBatis
Since I am asking a single question let's concentrate on the mapping which I consider the most important problem.
So my question is:
Is there any convenient solution to map the QueryDSL's SQLQuery results to the domain object, similar to what MyBatis or JPA offer? That is, the mapping based on some simple configuration, be it XML, annotations, or simple Java?
In particular, I am interested in the following:
Mapping a column to a custom type, e.g. a String column to an EmailAddress Java object
Mapping a group of columns to an embedded object, such as e.g. grouping {first_name, last_name} into a FullName Java object
Supporting one-to-many relationship, such as being able to extract a Customer object(s) containing a list of Addresses.
To summarize, I need an easy way to obtain one or many objects of the following 'Customer' class from the following SQL query:
class Customer {
EmailAddress emailAddress;
FullName fullName;
Set<Address> addresses;
Set<Comment> selfDescription;
}
class EmailAddress {
private String address;
EmailAddress(String address) {this.address = address; }
}
class FullName {
String firstName, lastName;
}
class Address {
String street, town, country;
}
class Comment {
LocalDateTime timeStamp;
String content;
}
Query:
query.from(qCustomer).
leftJoin(qCustomer._addressCustomerRef, qAddress)).
leftJoin(qCustomer._commentCustomerRed).
getResults(
qCustomer.email_address, qCustomer.first_name, qCustomer.last_name,
qAddress.street, qAddress.town, qAddress.country,
qComment.creation_time_stamp, qComment.content);
The ideal solution for me would be to reuse the MyBatis mapping infrastructure.
Another mapping solution or a custom one is also acceptable.
Note:
I could also accept "negative" answers if you show an alternative that:
Possesses an ease of use and transparency comparable to that of MyBatis - you always know which SQL is executed by simply inspecting the code
Allows full control over the executed SQL code, in particular, allows to easily write three DAO methods for retrieving 'Customer': without 'addresses' and 'selfDescription' information, just with 'addresses', and with all the fields
Allows compile-time check of your SQL code
Does not require hand-coding of mapping of every single domain class from SQL.
The alternative should work well on the example above.
Solutions already considered:
MyBatis 'Builder' class (http://mybatis.github.io/mybatis-3/statement-builders.html): not enough, since the column and table names are still Strings, so it violates requirement (3)
Spring-data + JPA + QueryDSL: might be an option if you show how the requirements (1) and (2) can be satisfied and if no simpler solution will be provided
Lukas Eder gave an excellent answer to a similar question here: Is it possible to combine MyBatis and QueryDSL/jOOQ?
His answer to the mapping question is to use either Java 8 functional style capabilities or a dedicated solution such as modelmapper.
He also mentioned Spring JCache support as a caching solution and this solution to the logging.

Resources