Spring jdbcTemplate passing constant value to an query method - java

Is it possible to mention an values as constant in the function. I have an entity say, EntityClass. Then a repository interface over it, say
interface EntityClassRepository extends CrudRepository<EntityClass, String> {
List<EntityClass> findById(String id);
}
Can I hard code some value in the method like,
List<EntityClass> findByIdAndActiveFlagAsY(String id);
To only query the ones where active flag column's value is 'Y'.
Is it possible?

No, spring data not support AS keywords inside method names, you can check all the Supported keywords inside method names :
So to solve your problem you can use custom query instead :
#Query("from EntityClass e WHERE id = :id AND ActiveFlag = 'Y'")
public List<EntityClass> findByIdAndActiveFlagAsY(#Param("id") String id);
Or you can use Equals keywords but you should to send the value in the method :
#Query("from EntityClass e WHERE id = :id AND ActiveFlag = :flag")
public List<EntityClass> findByIdAndActiveFlagEquals(#Param("id") String id, #Param("flag") String flag);

Related

Is there a way to return collection instead of entity in #Repository's #Query

I have a query:
#Query(
value = "select name, age, now() from received.scheme ;",
nativeQuery = true
)
public {???} selectData()
I cannot create or return an entity for such a scheme as there is no natural id in it, so is there a way to return something like List<Triple<String, Int, LocalDateTime>>?
you can create another class with the required properties which you want to retrieve from the database and then you can return that class as List<Class>.
In your code you get the data from: scheme
So the Entity SchemeEntity should contains those three fields:
name
age
now (creationDate for example it depend on your logic)
Then your method should be like this:
#Query(value = "select name, age, now() from received.scheme ;",
nativeQuery = true
)
public List<SchemeEntity> selectData();
You can provide a PROJECTION entity which will have 3 attributes and must provide a parametrized constructor with those 3 attributes you want to fetch ,or you can still get them as a List<Object[]> and then hydrate your entity.
I've tried those things but what worked for me is using ctid as an #Id. Since I only needed some sort of a mock id, it worked fine.

How to handle all enum value in JPA Query method for empty parameter

I have a JPA method that finds list of Students by their graduation status.
List<Student> findAllByStatus(Status status);
But if the request is made with null Status, I want to retrieve entities with null status.
How can I handle this with JPARepository using only one method query, to achieve no filtering by status if the status is null?
Thanks in advance.
You should use something like:
#Query("SELECT s from Student s WHERE (?1 is null or s.status = ?1)")
List<Student> findAllByStatus(Status status);
Just a little fix to Ankit Kanani answer.
Try
#Query("SELECT s from Student s WHERE (s.status is null or s.status =?1)")
List<Student> findAllByStatus(Status status);
This method involves a bit more code but i think it's your best bet :
#Override
public List<Interface> findAllWithFilters(String name, InterfaceType type, String ip)
{
Interface intfc = new Interface();
intfc.setName(name);
intfc.setType(type);
intfc.setIp(ip);
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("name", match -> match.contains())
.withMatcher("type", match -> match.exact())
.withMatcher("ip", match -> match.contains())
.withIgnorePaths("id", "uuid")
.withIgnoreNullValues();
Example<Interface> example = Example.of(intfc, matcher);
return ((InterfaceRepository) baseRepository).findAll(example);
}
The .withIgnoreNullValues() is the key. It will just return everything if you send a null value instead of an enum constant.
JPA is generating SQL statement with equal sign. Comparing null with equal sign does not work in most DBMS. Instead is keyword is needed:
WHERE (s.status =?1 and ?1 is not null) or (s.status is null and ?1 is null)

Spring Data JPA #Query with foreign key: Parameter not matched

I have a table "Signal" with id, volume and object_id columns.
Object_id is a foreign key. I need to retrieve each signal that has a particular object_id.
Im trying to use this Query
public interface SignalRepository extends JpaRepository<Signal, Integer> {
#Query("select s from Signal s where s.object = ?1")
Optional<List<Signal>> findSignalByObjectId(Integer objectId);
}
It doens't work. If I change "?1" to 1 it gets the hardcoded value. If I try to query the "volume", it works fine.
I get this error:
Blockquote
nested exception is java.lang.IllegalArgumentException: Parameter value [1] did not match expected type
I'd recommend you omit the query and let spring data generate one for you. So your case may be represented somehow like that (in case of proper relation mapping defined):
public interface SignalRepository extends JpaRepository<Signal, Integer> {
Optional<Signal> findByObject(YourObjectType object);
}
If you provide more info e.g. your entities - you can get more help.
You can use Spring data to generate the underlying query like this :
public interface SignalRepository extends JpaRepository<Signal, Integer> {
List<Signal> findSignalByObjectId(Integer objectId);
}
or you can write the query with this return type and parameter:
public interface SignalRepository extends JpaRepository<Signal, Integer> {
#Query("select s from Signal s where s.object = :id")
List<Signal> findSignalByObjectId(#Param("id") Integer objectId);
}

Spring Data JPA and Exists query

I'm using Spring Data JPA (with Hibernate as my JPA provider) and want to define an exists method with a HQL query attached:
public interface MyEntityRepository extends CrudRepository<MyEntity, String> {
#Query("select count(e) from MyEntity e where ...")
public boolean existsIfBlaBla(#Param("id") String id);
}
When I run this query, I get a java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Boolean.
How does the HQL query have to look like to make this work? I know I could simply return a Long value and afterwards check in my Java code if count > 0, but that workaround shouldn't be necessary, right?
Spring Data JPA 1.11 now supports the exists projection in repository query derivation.
See documentation here.
In your case the following will work:
public interface MyEntityRepository extends CrudRepository<MyEntity, String> {
boolean existsByFoo(String foo);
}
I think you can simply change the query to return boolean as
#Query("select count(e)>0 from MyEntity e where ...")
PS:
If you are checking exists based on Primary key value CrudRepository already have exists(id) method.
in my case it didn't work like following
#Query("select count(e)>0 from MyEntity e where ...")
You can return it as boolean value with following
#Query(value = "SELECT CASE WHEN count(pl)> 0 THEN true ELSE false END FROM PostboxLabel pl ...")
It's gotten a lot easier these days!
#Repository
public interface PageRepository extends JpaRepository<Page, UUID> {
Boolean existsByName(String name); //Checks if there are any records by name
Boolean existsBy(); // Checks if there are any records whatsoever
}
Since Spring data 1.12 you can use the query by Example functionnality by extending the QueryByExampleExecutor interface (The JpaRepositoryalready extends it).
Then you can use this query (among others) :
<S extends T> boolean exists(Example<S> example);
Consider an entity MyEntity which as a property name, you want to know if an entity with that name exists, ignoring case, then the call to this method can look like this :
//The ExampleMatcher is immutable and can be static I think
ExampleMatcher NAME_MATCHER = ExampleMatcher.matching()
.withMatcher("name", GenericPropertyMatchers.ignoreCase());
Example<MyEntity> example = Example.<MyEntity>of(new MyEntity("example name"), NAME_MATCHER);
boolean exists = myEntityRepository.exists(example);
Apart from the accepted answer, I'm suggesting another alternative.
Use QueryDSL, create a predicate and use the exists() method that accepts a predicate and returns Boolean.
One advantage with QueryDSL is you can use the predicate for complicated where clauses.
You can use Case expression for returning a boolean in your select query like below.
#Query("SELECT CASE WHEN count(e) > 0 THEN true ELSE false END FROM MyEntity e where e.my_column = ?1")
Spring data provides method for checking the existence of a row using field:
example: boolean existsByEmployeeIdAndEmployeeName(String employeeId, String employeeName);
You can use .exists (return boolean) in jpaRepository.
if(commercialRuleMsisdnRepo.exists(commercialRuleMsisdn.getRuleId())!=true){
jsRespon.setStatusDescription("SUCCESS ADD TO DB");
}else{
jsRespon.setStatusCode("ID already exists is database");
}

Selecting fields on Spring Data

I'm trying to find information about how to select only certain fields of an entity using Spring Data (I'm using JPA). I want to select only specific information of an entity, the repository interfaces gives you the ways to return the information of the WHOLE entity!. Some times I only need 2 or 3 fields of an entity and returning 20,30, ...100.. fields may be a little overkill.
This kind of functionality is something that I would do using Hibernate Criteria Projections, or even JPA "SELECT NEW ...." queries. Don't know if it is possible with Spring Data.
Thanks.
What you can do is return a List<Object[]> from repository. Then in your service class iterate over this list and manually create the object you need. Sample repository method
#Query("select el.moduleId, el.threadId from ExceptionLog el")
public List<Object[]> tempQuery();
I think you can also do it in this way
SomeDataPOJO{
required col1
required col2
}
and then write query like this
#Query("select new SomeDataPOJO from requiredTable where xyz="abc")
public List<SomeDataPoJO> tempQuery()
Its not plain Spring Data but did you consider using Springs JdbcTemplate? Its also in the Context if you use Spring Boots Autoconfiguration and has several handlers for transforming results of the Query.
For Example for the Query SELECT a, b FROM EMPLOYEE WHERE ID = ? you could use
String query = "SELECT a, b FROM EMPLOYEE WHERE ID = ?";
List<Pair<String,Integer>> employees = jdbcTemplate.queryForObject(
query, new Object[] { id }, new ExampleRowMapper());
Where the ExampleRowMapper transforms each row from the result into your given Return type (Pair<String, Integer> in this case) and could look like
public class ExampleRowMapper implements RowMapper<Pair<String, Integer>> {
#Override
public Pair<String, Integer> mapRow(ResultSet rs, int rowNum) throws SQLException {
return Pair.of(rs.getString(1), rs.getString(2));
}
}
Example adapted from https://www.baeldung.com/spring-jdbc-jdbctemplate where you find more information.
Of course its not as typesafe as a JPQL as the Query is "raw" or "native" SQL but at least the response is again typesafe and I like it more than to return Object[] or something.

Categories

Resources