Query by Date in Java Spring Data JPA - java

ETA: TL;DR:
orderRepo.save() converts the date (input):
Wed Jun 22 00:00:00 CDT 2022
into this (output):
2022-06-22 05:00:00.000
I am wondering how I can convert the input into the output, in Java, without putting it in the database first.
Original post:
I have a website that has been working with java.utils.Date for over a year now. I can use the angular date picker which makes an order object, sends it to java, repo.save() puts it in the database, pulls it back to angular and displays the date just fine.
I am now trying to query only a specific date from the DB.
#Query("SELECT o FROM Order o JOIN o.boats b WHERE b.date = ?1")
Set<Order> findByDate(Date date);
However this keeps turning up empty even though there are dates that match in the DB
How do I fix my query to grab those dates?
I know, "Don't use java.util.Date" but that is the system I am working with and I don't have time at the moment to convert everything to LocalDate. I will at some point but I am already quite behind on current tasks.
Thanks!!

This method is a jpql
I would have used another way.
Interface call method or Query methods
By calling a method request in the interface, we need our user interface to inherit the interface specified in the Spring Data Jpa:
public interface UserDao extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User>
The prerequisite for using these methods is that the entity class you define should be marked with appropriate annotations.
#Entity //Mark this as an entity class
#Table(name = "tbl_user") //Setting the mapping relationship between the entity class and the public class User table {
#Id //Declare this attribute as the primary key
#GeneratedValue(strategy = GenerationType.IDENTITY) //Primary key generation strategy, self-reinforcing
#Column(name = "user_id") //The specified attribute corresponds to the column name of the database table
private Integer userId;
#Column(name = "user_name")
private String userName;
#Column(name = "user_address")
private String userAddress;
#Column(name = "user_salary")
private Double userSalary;
//... setter method toString
}

Related

Spring Boot custom query group by and count

I'm having a problem with accessing data from a custom query.
Here is the POJO:
#Getter
#Setter
#NoArgsContructor
#AllArgsConstructor
#Entity
#Table(name = "run_list")
public class RunList {
#Id
#Column(name = "id")
private Long id;
#Column(name = "control_run_name"
private String serverName;
#Column(name = "control_run_date"
private Date controlRunDate
<.. bunch of other fields .. >
Here is the repository:
public interface RunListRepository extends JpaRepository<RunList, Long> {
#Query("SELECT u.serverName,count(u) as controlRunCount from RunList u where u.controlRunDate < :lastUploadDate group by u.serverName")
List<RunList> findAllControlRunAfterDate(#Param("lastUploadDate") Date lastUploadDate);
In the controller I invoke the repository method like so:
Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2020-03-01");
model.addAttribute("runList",runListRepository.findAllControlRunAfterDate(date);
The binding to the date in the query works ok I get a first result of the group by so that is solved. The thing is I get an error while runing this :
Failed to convert from type[java.lang.Object[]] to type [#org.springframework.data.jpa.Query my.package.name.RunList} for value '{server1,14}';
When I use the SQL query against the database from it's CLI I get a nice grouping of the serverName and the count.
I'm guessing the problem is in the conversion of the count field that is popping out of nowhere from the repository method and Spring doesn't know what to link this too.
I've tried to use a RunListDTO here that has only a String serverName and an Ingeter controlRunCount with no luck - the repository interface didn't like me using a DTO in the output of a method used in a interface created with .
Is there a way to make this a custom Array/Object in flight when the repository does the count?
Regards,
Jarek.
Since you are selecting a field and a count there is no way it can be mapped to your entity, so this query returns an array of values you specified, like you can see in the exception: '{server1,14}'.
public interface RunListRepository extends JpaRepository<RunList, Long> {
#Query("SELECT u.serverName,count(u) as controlRunCount from RunList u where u.controlRunDate < :lastUploadDate group by u.serverName")
List<Object[]> findAllControlRunAfterDate(#Param("lastUploadDate") Date lastUploadDate);
So in your service you can work with this data like:
List<Object[]> list = runListRepository.findAllControlRunAfterDate(yourDate);
for (Object[] ob : list){
String serverName = (String)ob[0];
Integer count = (Integer)ob[1];
}

what to use instead of fetch.EAGER in spring data?

I'm working with spring-boot and angular5 , i have this entity in spring :
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Contrat implements Serializable{
#Id #GeneratedValue
private Long id;
private Date dateDebut ;
private Date dateFin ;
#ManyToOne
#JoinColumn(name = "Id_Project")
#JsonBackReference(value="projet-contrat")
private Project project;
#ManyToOne
#JoinColumn(name = "Id_AppUser")
#JsonBackReference(value="appuser-contrat")
private AppUser appUser;
}
A repository :
public interface ContratRepo extends JpaRepository<Contrat,Long> {
public Page<Contrat> findByAppUser(#Param("userApp") AppUser userApp, Pageable pageable);
}
As the fetch.lazy is the default one , when i try to call the method findByAppUser i get as result :
{id: 1, dateDebut: 1526083200000, dateFin: 1526083200000}
Which is normal , what i want for my case is to load also the object 'project' that exists in the entity , but i don't wan't to use the fetch.EAGER , any solution for this goal ?
Your entity is one-many relationship object. If you don't use EAGER, spring data will get the object without related member object. And if you get that with contract.getProject().getName(), then another query will be sent to get that member.
If you log the SQL, you can see that, there will be 2 queries. But if you set the field as EAGER, there will be only 1 query. You can get improvement obviously.
But you should not use EAGER always. If in 90% of time, you just need the Contract object, but no need the project data of it. It is a waste of time to get that. Because in SQL, it will relate 2 tables and get all columns of data.
SO, you should make this decision based on your usage of this entity.
[Updated based on comment]
You can use Query to write your sql expression. for example, I have a method to get the entity with detail:
#Query("select s from Contract s left join fetch s.project pr where s.id = ?1 ")
Contract findOneWithDetail(Long id);
If I need to get the detail in ONE sql, I can use this method. If I don't need the project detail, I just use findOne(Long id), which is provided interface.
And, if you just want to get some columns, you need to define a DTO, with a constructor, and write your method like this:
#Query("SELECT NEW com.mypackage.dto.ContractDTO(s.id, s.name, s.status) FROM Contract AS s WHERE s.status = ?1")
List<ContractDTO> findDTOAllByStatus(String status);
Provide the query in your repo method, e.g. (syntax may be wrong, just show you the idea)
public interface ContratRepo extends JpaRepository<Contrat,Long> {
#Query(query="from Contrat c left join fetch c.project " +
"where c.userApp = :userApp")
public Page<Contrat> findByAppUser(#Param("userApp") AppUser userApp, Pageable pageable);
}

#DateTimeFormat and TO_DATE() pattern for Calendar type passed through rest service

I'm working on Web application which is using Spring Data JPA and Oracle Database. I was using #RepositoryRestResource annotation in interface where I was just declaring some query methods with named parameters using #Param and #Query annotations. Today I needed to add a new entity with the dates. In database one column is type of DATE and the other one is type of TIMESTAMP. And below the Java representation of this two columns only, of course with all setters and getters, but it has more fields so just adding this:
#Temporal(TemporalType.DATE)
#Column(name = "INIT_DATE")
private Calendar initDate;
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "AGG_DATE")
private Calendar aggDate;
I also created new interface for case, the same way as always:
#RepositoryRestResource(collectionResourceRel = "customer", path = "customer")
public interface ICustomerRepository extends PagingAndSortingRepository<Customer, Long> {
#Query("SELECT c FROM Customer c where c.initDate <= TO_DATE(:currentDate, 'yyyy-MM-dd') AND c.aggDate >= TO_DATE(:currentDate, 'yyyy-MM-dd')")
public List<Customer> filterByDate(#Param("currentDate") #DateTimeFormat(pattern = "yyyy-MM-dd") Calendar currentDate);
}
I also tried other format, but I'm receiving this error:
ORA-01830: date format picture ends before converting entire input string
I'm trying to get this data from database using this http request:
http://localhost/webApp/customer/search/filterByDate?currentDate=2017-07-10
And to be honest, I have no idea what is the problem here... The format date in the database is yy/MM/DD, but it also wasn't working for me... Could you tell me what I'm missing or doing wrong??

Spring Boot + Spring Data JPA query from java.util.Date type using only the month

I'm using Spring Boot 1.4.0 with Spring Data JPA 1.10.2, and I find myself in an impasse to create a query like this:
SELECT * FROM myDatabase
WHERE
MONTH(nascimento) = '11';
My goal is list all birthdays of the current month, of a field with sql format year-month-day.
In my #Entity, I store a java.util.Date type attribute, named nascimento.
#Entity
public class Cliente {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#NotEmpty
private String nome;
#NotNull
private Date nascimento;
// Get/Set...
}
In my #Repository I use the Spring Data CrudRepository interface.
#Repository
public interface ClienteRepository extends CrudRepository<Cliente, Integer> {
// Methods...
}
Is there any way to perform a query using only the month on attribute of java Date type?
I would like to create an interoperable query between relational DBMS using the Query methods supported by Spring Data framework.
Currently I solve this problem with this approach (but I believe it is not appropriate for all Databases):
#Query(value = "SELECT * FROM Cliente WHERE MONTH(nascimento) like ?1", nativeQuery = true)
Iterable<Cliente> findAllByNascimentoLike(String Month);
To think of the solution, and if necessary use the month and day?
Thanks for trying to help me.
Use JPA Query Expressions this language is independent of the database. The JPA query expresion it would be similar to your native Query (you may use function MONTH):
#Query("SELECT u FROM Cliente u WHERE MONTH(u.nascimento) = ?1")
Iterable<Cliente> findAllByNascimentoLike(Integer month);

How to query RevisionEntity in hibernate envers

I was trying to log additional user data with the revisions created by Envers. I was able to do that using RevisionEntity and RevisionListener but I'm not able to retrieve the data that is logged.
I tried the following code
AuditQuery auditQuery = AuditReaderFactory
.get(factory.getCurrentSession()).createQuery()
.forRevisionsOfEntity(Currency.class, false, false)
.add(AuditEntity.id().eq("ENV_US"));
List<Object[]> l = auditQuery.getResultList();
This returned a List
In the object array first element is the Revision Second is of RevisionEntity and third is of RevisionType, but the values in RevisionEntity object are all null.
Here is the pojo for RevisionEntity
#Entity
#Table(name = "REVINFO")
#RevisionEntity(RevListener.class)
public class ExampleRevEntity {
#Id
#GeneratedValue
#RevisionNumber
#Column(name = "REV")
private int rev;
#RevisionTimestamp
#Column(name = "REVTSTMP")
private long revtstmp;
#Column(name = "USERID")
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
Please let me know If I'm doing any thing wrong.
You may need to actually use the object. Hibernate/Envers will return a lazy initialized object, and debuggers will probably not be able to see the values. Once you call the getters in code, the proper values should be populated.
Do you want to query the revision entity itself, or retrieve audited objects including the revision entity?
If you want to query the revision entity itself, it's a completely normal entity. Just query it as all other entities - not through an AuditQuery, but using an EntityManager or Session.
If you want to retrieve audited objects including the revision entity, then the above is correct, provided that there exist revision data for the revisions at which the object changed. Do you see data in the database corresponding to the returned revisions?

Categories