Spring Data JPA passing dynamic column names as parameter to query - spring

I have table emp with columns emp_name, emp_desc, emp_age, emp_country, emp_pincode.
I am using Spring data Jpa for database operations.
#Repository
public interface EmpRepository extends JpaRepository<Emp, String> {}
and empRepository.findAll(); fires a select * from emp table.
But I have a requirement like as follows
The client app would pass column names to select in the method as parameter and I want to fetch only those in Jpa not Findall().
How to acheive this in Jpa?

Try this one
To get the employee details based on emp_name
empRepository.findByEmpName(String empName);

Related

How to get a List in one of the fields of DTO JPA Repository

I have a DTO and one of its field is a list. So, there is a main table and another table with one to many relations.
Code:
public class DTO {
id;
List<String> name;
}
public interface Repository extends JpaRepository<Table1, Long> {
#Query("SELECT new abc.com.DTO (" +
" r.id," +
" name"+
" )" +
" FROM Table1 r" +
" join Table2 c on c.xyz.id = r.abc.id"+
" WHERE r.type = :type"
)
List<DTO> find(#Param("type") final String type);
}
say I have in table T1 a row against which we have 3 rows in table 2.
I want dto to get me object obj1 with a list of all 3 names for table2
Currently it returns me 3 separate dtos with 3 rows of table2
As it is stated in the JPA specification (see section 4.8 SELECT Clause):
The SELECT clause can contain one or more of the following elements: an identification variable that ranges over an abstract schema type, a single-valued path expression, a scalar expression, an aggregate expression, a constructor expression.
Note that the SELECT clause must be specified to return only single-valued expressions. So, the query like below is therefore not valid:
SELECT o.lineItems FROM Order AS o
This is not possible with JPA directly as constructor expressions always use flat results. Spring Data Projections should support this, but in an inefficient way i.e. it selects entities and just provides a "view" of these entities through an interface.
I think this is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
#EntityView(Table1.class)
public interface DTO {
#IdMapping
Long getId();
#Mapping("Table2[xyz.id = VIEW(abc.id)].name")
Set<String> getNames();
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
DTO a = entityViewManager.find(entityManager, DTO.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
public interface Repository extends JpaRepository<Table1, Long> {
List<DTO> findByType(#Param("type") final String type);
}

Properly evaluate placeholders in materialised view from JdbcTemplate

Here is my case:
I have the following sql file (my_view.sql - containing the definition of a materialised view, Oracle dialect) returning all the products having expire_date > sysdate:
CREATE MATERIALIZED VIEW my_view
BUILD DEFERRED
REFRESH COMPLETE ON DEMAND
AS
SELECT *
FROM product
WHERE expire_date > sysdate
Now in the application code I have a Spring Service using this view:
#Service
public class MyService {
private final JdbcTemplate jdbcTemplate;
#Value("${expire_date}")
private String expireDate;// property will be injected at runtime by Spring, but how to pass this string to be evaluated in the sql script through jdbcTemplate
public MyService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void callMaterialisedView() {
try (Connection zs1DbConnection =
jdbcTemplate.getDataSource().getConnection()) {
jdbcTemplate.execute("BEGIN dbms_mview.refresh('my_view', 'c');END;");
}
}
}
My question: Is it possible to make expire_date configurable and pass it from the application code as a placeholder to the sql script?
Making it configurable is easy - i can use Spring #Value annotation to inject a concrete value to my application code. What I miss is how (if possible at all) to pass this value from jdbcTemplate to the script to be evaluated properly.
In the final variant, I imagine the script to look like (expire_date being passed from jdbcTempalte):
CREATE MATERIALIZED VIEW my_view
BUILD DEFERRED
REFRESH COMPLETE ON DEMAND
AS
SELECT *
FROM product
WHERE expire_date > to_date(${expire_date})
The materialized view does not accept a parameter, but you can create a dummy table with one column and insert/update your parameter value in table.
It's an alternative solution.
In MV SQL you can write something like " where expire_date > (select dt_col from dummy_tab) " as below:
CREATE MATERIALIZED VIEW my_view
BUILD DEFERRED
REFRESH COMPLETE ON DEMAND
AS
SELECT *
FROM product
WHERE expire_date > (select dt_col from dummy_tab);

How to avoid slow request to use envers at Spring boot

I am using envers at Spring boot project.
#Repository
public interface DataAudRepository extends RevisionRepository<Data, String, Integer>, JpaRepository<Data, String> {
}
If there is numerous data on the data_aud table (data number : 3500), request of findRevisions(key, pageable) is very slow.
Sure if there is not numerous data, request is argent.
When Spring call this function, some of hiberate sql occur.
select *
from data_aud publish_au0_
where
data_au0_.rev=(
select max(data_au1_.rev) from data_aud data_au1_
where
data_au1_.rev<=999999 and
data_au0_.data_id=data_au1_.data_id) AND
data_au0_.data_id='my-data-01'
Perhaps i think select max sequence is reason for slow request.
How to avoid this slow condition?
+)
Primary key of data_aud table is (data_id, varchar(32), rev, int(11))
and PK of data table is data_id.

Spring data jpa query to return with multiple properties

I have to fetch Users by id and state.The method takes a set of usersIds as input.
I need a jpa query like below:
public Set<Users> fetchUsersByIdsContainingStateId(Set<Integer> userIds, Integer stateId)
Is there a query like the above in Spring Data JPA or I need to resort to named query
you can use spring data query:
public interface UserRepository extends CrudRepository<User, Long> {
Set<User> findUserByIdInAndStageId(Set<Long> userIds , Long stageId);
#Query("select u from User u where u.id in (:userIds) and u.stage.id=:stageId")
Set<User> findUserByUserIdsAndStageId(#Param("userIds") Set<Long> userIds , #Param("stageId") Long stageId);
}
for method findUserByIdInAndStageId spring data generates something
like
-- whereuser0_.id in (? , ? , ?...)) and stage1_.id=?
method findUserByUserIdsAndStageId do the same as findUserByIdInAndStageId , but in Query annotation you should write your query.
second search method findUserByUserIdsAndStageId named just for example , but I'll change it into something more readable like findUserWithStage(......)
PC don't use for domain model plural name like Users , use singular User

Intreceptor in spring

I want know about, from where the onsave() method gets arguments?
Example:
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types)
This method should come from hibernate interceptor interface (org.hibernate.Interceptor).Spring may provides some built-in beans that implements this interface .
This method is supposed to be called when an new entity is first saved by the hibernate session. For example , suppose you map the EMPLOYEE table to the employee object and you create a new employee record using the following codes:
Employee employee = new Employee();
employee.setName("Peter");
employee.setJoinDate(new Date());
employee.setExtNumber(1234);
/*seesion refer to the Hibernate session*/
session.save(employee);
Hibernate will then generate the following INSERT SQL :
insert into EMPLOYEE (NAME, JOIN_DATE , EXT_NUMBER) values ("Peter" , to_date('2011-6-20') , 1234)
Before the above SQL is issued to the DB , and if there an interceptor enable , hibernate will call onSave() method with the following parameters:
entity : The employee reference that is being saved
id : PK of the new employee record
state : Arrays containing the values of different fields for the INSERT SQL (i.e. Array
containing the value "Peter" , new Date() , 1234)
propertyNames : Arrays containing the name of the columns for the INSERT SQL (i.e Array containing the string "NAME" , "JOIN_DATE" , "EXT_NUMBER")

Resources