jpa findby with list of conditions - spring

I am still a beginner with java, here I'm trying to fetch the data from mysql database using JPA.
but I'm getting a problem with setting the list of conditions with find by function.
i can set Object of date even it refused the inputs
below is my code for reference.
my query :
select t.id, t.MSISDN, t.Param1, t.param2
from BULK_REPOSITORY t
where t.Camp_Start_Date between Sysdate - 2 and sysdate
and t.status = 0
and t.camp_type = 1;
Application :
#SpringBootApplication
public class AccessingDataJpaApplication {
private static final Logger log = LoggerFactory.getLogger(AccessingDataJpaApplication.class);
Bulk_repository bulk ;
public static void main(String[] args) {
SpringApplication.run(AccessingDataJpaApplication.class);
}
#Bean
public CommandLineRunner demo(Bulk_repositoryRepository repository) {
return (args) -> {
// fetch customers by Status
log.info("Customer found with findByStatus('0'):");
log.info("--------------------------------------------");
repository.findAllByStatusAndCampTypeAndCampStart_dateBetween(1,2,Date,Date-2).forEach(on -> {
log.info(on.toString());
});
};
}
Bulk_repositoryRepository class :
import org.springframework.data.repository.CrudRepository;
public interface Bulk_repositoryRepository extends CrudRepository<Bulk_repository, Long> {
List<Bulk_repository> findAllByStatusAndCampTypeAndCampStart_dateBetween(int status, int campType,Date campStart_dateStart, Date campStart_dateEnd);
Bulk_repository findById(long id);
}
Bulk_repository:
#Entity
#Table(name = "BULK_REPOSITORY")
public class Bulk_repository {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "msisdn")
private String msisdn;
#Column(name = "camp_start_date")
private Date campStartDate;
#Column(name = "camp_end_date")
private Date campEndDate;
#Column(name = "camp_type")
private int campType;
#Column(name = "camp_cd")
private String camp_cd;
#Column(name = "status")
private int status;
#Column(name = "process_date")
private Date processDate;
#Column(name = "entry_date")
private Date entryDate;
#Column(name = "entry_user")
private String entry_user;
#Column(name = "param1")
private String param1;
#Column(name = "param2")
private String param2;
#Column(name = "param3")
private String param3;
#Column(name = "param4")
private String param4;
#Column(name = "param5")
private String param5;
#Column(name = "error_desc")
private String error_desc;
#Column(name = "fulfilment_status")
private int fulfilment_status;
## getter and setter and ToString

Use this way,
Escape the _ by using an additional underscore
List<Bulk_repository> findAllByStatusAndCamp__typeAndCamp__start__dateBetween(int status, int camp_type,Date camp_start_dateStart, Date camp_start_dateEnd);
I recommond to use this way in your model class. If so you have to change your repository according to this.
#Column(name = "camp_start_date")
private Date campStartDate; // better to use this way

Related

Auto populate created_date, last_modified_date, created_by and last_modified_by in entity : Hibernate with JPA

I am new to Hibernate and JPA. I have several entities, each of which contains following four columns:
1. created_by
2. last_modified_by
3. created_date
4. last_modified_date
I would like these columns to get auto-populated while saving the associated entity.
Two sample entities are as follows:
Entity 1:
#Entity
#Table(name = "my_entity1")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity1 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name")
private String name;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
Entity 2:
#Entity
#Table(name = "my_entity2")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class MyEntity2 implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "description")
private String description;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private String lastModifiedDate;
}
In this context, I have gone through following posts: How to autogenerate created or modified timestamp field?, How can you make a created_at column generate the creation date-time automatically like an ID automatically gets created?.
I am getting how to capture the dates fields but I cannot understand how to capture created_by and last_modified_by.
Auditing Author using AuditorAware and Spring Security...
To tell JPA about currently logged in user we will need to provide an
implementation of AuditorAware and override getCurrentAuditor()
method. And inside getCurrentAuditor() we will need to fetch currently
logged in user.
Like this:
public class AuditorAwareImpl implements AuditorAware<String> {
#Override
public String getCurrentAuditor() {
return "TestUser";
// Can use Spring Security to return currently logged in user
// return ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername()
}
}
Now enable jpa auditing by using #EnableJpaAuditing
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JpaConfig {
#Bean
public AuditorAware<String> auditorAware() {
return new AuditorAwareImpl();
}
}
Look at this to get more details....

JpaSystemException when trying to fetch null values from Database

for some cases the master Id is null in DB and when I am fetching it it is giving me JPA system exception
So is there any annotation that would help to ignore the null values.
Method threw 'org.springframework.orm.jpa.JpaSystemException' exception.
got it when trying to fetch details from the database.
package com.merchant.orderDahsBoard.controller;
#RestController
#RequestMapping(value = "Dashboard")
public class OrderDashboardController {
#Autowired
private DashBoardService service;
ObjectMapper mapper = new ObjectMapper();
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
#PostMapping(value = "/getOrderDetails")
public OrderResponse getOrder(#PathParam(value = "id") Long id) {
OrderResponse response = new OrderResponse();
List<OrderMapping> orderMapping;
Sale sale= new Sale();
Purchase purchase = new Purchase();
long saleId = 0;
long purchaseId = 0;
try{
orderMapping = service.getOrderMapping(id);
response.setOrderMapping(orderMapping);
if (orderMapping != null) {
for (OrderMapping order : orderMapping) {
switch (order.getORDERTYPE()) {
case CART:
break;
case SALE:
saleId = order.getORDERID();
break;
case PURCHASE:
purchaseId = order.getORDERID();
break;
}
}
if(saleId!=0){
sale = service.getSale(saleId);
response.setSale(sale);
}
}
}
catch(Exception e){
log.error("Exception occured "+e);
}
return response;
}
}
below is the #Entity Class used in my project
#Entity
#Table(name = "ORDERMAPPING")
#Getter
#Setter
#ToString
public class OrderMapping {
#Id
#Column(name = "ORDERMAPPINGID")
private long ORDERMAPPINGID;
#Column(name = "MASTERID")
private long MASTERID;
#Column(name = "ORDERID")
private long ORDERID;
#Enumerated(EnumType.ORDINAL)
private OrderTypeEnum ORDERTYPE;
#Column(name = "ADDEDDATE")
private String ADDEDDATE;
#Column(name = "LASTUPDATEDDATE")
private String LASTUPDATEDDATE;
#Column(name = "CARTID")
private long CARTID;
#Column(name = "PCARTID")
private long PCARTID;
}
Instead of primitive data types try using the wrapper classes for the same. The following code can help you better.
Use Long isntead of long
#Entity
#Table(name = "ORDERMAPPING")
#Getter
#Setter
#ToString
public class OrderMapping {
#Id
#Column(name = "ORDERMAPPINGID")
private Long ORDERMAPPINGID;
#Column(name = "MASTERID")
private Long MASTERID;
#Column(name = "ORDERID")
private Long ORDERID;
#Enumerated(EnumType.ORDINAL)
private OrderTypeEnum ORDERTYPE;
#Column(name = "ADDEDDATE")
private String ADDEDDATE;
#Column(name = "LASTUPDATEDDATE")
private String LASTUPDATEDDATE;
#Column(name = "CARTID")
private Long CARTID;
#Column(name = "PCARTID")
private Long PCARTID;
}

Get data from multiple tables using one Mapping Table in Spring Boot

Procedure.java
#Entity
#Table(name = "procedures")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Procedure implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ProcedureId")
private int id;
#Column(name = "ProcedureName")
private String name;
#Column(name = "ProcedureCode")
private String code;
#Column(name = "ProcedureDesc")
private String desc;
// getters and setters
}
CPTClinicianDescriptor
#Entity
#Table(name = "cliniciandescriptor")
public class CPTClinicianDescriptor {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private int id;
#Column(name = "ConceptId")
private int conceptId;
#Column(name = "CPTCode")
private String cptCode;
#Column(name = "ClinicianDescriptorId")
private int clinicianDescriptorId;
#Column(name = "ClinicianDescriptor")
private String clinicianDescriptor;
// getters and setters
}
CPTProcedures
#Entity
#Table(name = "cptprocedures")
public class CPTProcedures {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Id")
private int Id;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "ProcedureId")
private Procedure procedure;
#Transient
private int procedureId;
#OneToOne(fetch=FetchType.EAGER)
#JoinColumn(name = "CPTCodeSet")
private CPTClinicianDescriptor cptClinicianDescriptor;
#Transient
private int cptCodeSet;
// getters and setters
}
Here I have 3 table in mySql in those 2 are different separate tables, I created one table for Mapping that has foreign keys of Procedures and CPT when i get a list using Procedure It should get corresponding cpt data also.
ServiceImpl Like:
public List<Procedure> getCombinedProcedureList(int id) {
// TODO Auto-generated method stub
List<Procedure> pList = new ArrayList<Procedure>();
Procedure procedureList = procedureRepository.findCombById(id);
pList.add(procedureList);
return pList;
}
When i use
Repository like
#Query(value = "SELECT * FROM procedures JOIN cliniciandescriptor ON cliniciandescriptor.Id = ?1",nativeQuery = true)
Procedure findCombById(int id);
this query in Procedures Repository it is getting only procedures. So, what can i do to get the combined(joined) list of 2(procedures & CPT) tables using 3rd mapping table.

JPA Specification filtering nested object

I am trying to fetch nested object property but getting illegalArgument exception.
AuditTestingPlanSpecification name = new AuditTestingPlanSpecification(new SearchCriteria("auditPlanId.auditPlanEntity", ":",dates));
Page<AuditTestingPlanMaster> a = auditTestingPlanMasterRepository.findAll(name, ten);
Please find below code,
public class AuditTestingPlanSpecification implements Specification<AuditTestingPlanMaster> {
private SearchCriteria criteria;
public AuditTestingPlanSpecification(SearchCriteria searchCriteria) {
this.criteria = searchCriteria;
}
#Override
public Predicate toPredicate(Root<AuditTestingPlanMaster> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
if (root.get(criteria.getKey()).getJavaType() == String.class) {
return builder.like(root.<String>get(criteria.getKey()), "%" + criteria.getValue().get(0).toString() + "%");
} else {
return builder.equal(root.get(criteria.getKey()), criteria.getValue().get(0).toString());
}
return null;
}
}
Class SearchCriteria.java
public class SearchCriteria {
public SearchCriteria(String key, String operation, List<Object> value) {
super();
this.key = key;
this.operation = operation;
this.value = value;
}
private String key;
private String operation;
private List<Object> value;
// getters & setters
}
Class AuditTestingPlanMaster.java
#Entity
#Table(name = "audit_testing_plan_master")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class AuditTestingPlanMaster implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "risk_area_id")
private Long riskAreaId;
#Column(name = "expected_revert_date")
private Instant expectedRevertDate;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private Instant lastModifiedDate;
#JoinColumn(name = "audit_plan_id", referencedColumnName = "id")
private AuditPlanMaster auditPlanId;
//getters & setters
}
Class AuditPlanMaster.java
#Entity
#Table(name = "audit_plan_master")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class AuditPlanMaster implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
#Column(name = "remarks", length = 255)
private String remarks;
#Column(name = "audit_plan_entity", length = 50)
private String auditPlanEntity;
#Column(name = "start_date")
private Instant startDate;
#Column(name = "end_date")
private Instant endDate;
//getters & setters
}
I want to fetch all the AuditTestingPlanMaster objects whose AuditPlanMaster.auditPlanEntity string is matching with provided filter value.
Thank you for your time and help in advance.
I had the same problem, here is a snippet of how I handled it. My problem was when accessing id field from inner usuario object, in my case, id would be like your auditPlanEntity, and usuario would be like auditplanMaster:
public static Specification<UsuarioErrorEquipo> usuarioContains(String codigoUsuario) {
return (root, query, builder) -> {
Path<Usuario> u = root.get("usuario");
return builder.equal(u.get("id"), codigoUsuario);
};
}
I believe, that in your case it should be something like:
Path<AuditPlanMaster> u = root.get("auditPlanId");
return builder.equal(u.get("auditPlanEntity"), "the value you want to compare");

SQL to JPQL, How to query Nested JPQL

I wonder if JPQL can be nested query. I am studying Spring Data JPA, and I also have uploaded several related questions.
If I have below sql in MySQL, how do I produce JPQL:
select
c.*
from
cheat c
left join (select * from cheat_vote where val = 1) v on c.cheat_seq = v.cheat_fk
group by
c.cheat_seq
having
count(*) < 10
limit 5
I have two entities.
public class Cheat implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "cheat_seq", length = 10)
private Long cheatSeq;
#Column(name = "question", unique = true, nullable = false)
private String question;
#Column(name = "answer", unique = true, nullable = false)
private String answer;
#Column(name = "writer_ip", nullable = false)
private String writerIP;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "reg_date", nullable = false)
private Date regDate;
#Transient
private String regDateText;
#OneToMany(mappedBy = "cheat", fetch=FetchType.LAZY)
private Set<CheatVote> vote;
#Override
public String toString() {
return "Cheat [cheatSeq=" + cheatSeq + "]";
}
}
Above entity has a #OneToMany collection, and the collection entity is below.
public class CheatVote implements Serializable{
private static final long serialVersionUID = 1L;
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Id
#Column(name="seq", nullable=false)
private Long seq;
#Column(name="val", nullable=false)
#NonNull
private Integer value;
#Column(name="ip_address", nullable=false)
#NonNull
private String ipAddress;
#JoinColumn(name="cheat_fk", referencedColumnName="cheat_seq")
#ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
#NonNull
private Cheat cheat;
#Override
public String toString() {
return "CheatVote [seq=" + seq + "]";
}
}
I want to get Cheat entitiy which has less than 10 children CheatVote entities.
You can try it:
#Query("SELECT c FROM Cheat c LEFT JOIN c.vote v WHERE v.value = 1 GROUP BY c.cheatSeq HAVING count(c) < 10")
About 'LIMIT' you can use parameter Pageable of Spring Data JPA

Resources