Join and where clause using Criteria in Spring boot - spring-data-jpa

I'm trying to achieve something which is easily doable using named query but i want to do this using criteria.
Below are my two tables.
Notification:
id
userId (foreign key to user)
Notification
Visible
User:
userId,
name,
address
No I want to fetch notifications corresponding to a user (user id given) which are visible (value set to 1)
One way to do it to fetch notifications from User and iterate them to see which notification is visible, but i dont want to do that, as that will unnecessarily pull lots of data from db.
What should be the best way to do it?

You can use Spring data jpa to achive this with ease
create an interface extending JPA repository as
#Repository
#RepositoryRestResource
public interface NotificationRepository extends JpaRepository<Notification,Long (datatype for primary key)> {
List<Notification> findByUseridAndVisible(Long userid,int visible);
}
Now you can create service class and directly use this method as
class service(){
#Autowired
NotificationRepository notificationrepository;
public void method(){
Long userid=85;
int visible=1;
List<Notification> getnotificationlist= notificationrepository.findByUseridAndVisible(userid,visible);
}
}
Hope this will help you .

Related

JPA: How to get results by compromised where-clause

I have a table with 30 columns.
I fill the object within my java code. Now I want to look up in my database, if the row is already inserted. I can do this primitive like:
SELECT *
FROM tablename
WHERE table.name=object.name
AND table.street=object.street
AND ...
AND ...
AND ...
I think you get it. It works, but in my opinion this is not the best solution.
Is there any kind of a generic solution (eg: I do not need to change the code, if the table changes), where I can give the where-clause my object and it can match itself? Also the where-clause is not that massive.
The closest thing that comes to mind is the Spring Data JPA Specifications.
You can isolate the where clauses in an instance for a particular entity.
Afterwards, you just pass it to any of the #Repository methods:
public interface UserRepository extends CrudRepository<User, Long>,
JpaSpecificationExecutor<User> {
}
Then in your service:
#Autowired
private UrerRepository repo;
public void findMatching() {
List<User> users = repo.findAll(new MyUserSpecification());
Then, whenever db changes you simply alter one place, which is the Specification implementation.

Convert Spring's Order to JPA Order from Pageable

Our frontend is designed to send Pageable object with Spring's Order which contains attribute name.
Sample Entity:
#Entity
#Table
public class Foo {
private String userName;
#Embedded
private Bar bar;
}
#Embeddable
public class Bar {
private String value;
}
We receive pageable with order in repository and parse JPA's Order from that pageable object like this:
pageable.getSort().get().forEach(springOrder ->
jpaOrders.add(getBuilder().asc(root.get(springOrder .getProperty())))
);
We need do it this way because we are building queries via criteria api.
When we receive in repository attribute of Foo, everything is fine, e.g. "userName". But when we receive attribute of embeddable entity, e.g. "bar.value" we got exception
Unable to locate Attribute with the the given name [bar.value] on this ManagedType
Can you tell me how to create JPA's Order object from attribute which define attribute of embeddable entities? Thank you in advice
For these property paths you will have to create joins and apply the Order using the proper join alias and the last part of the property path.
For more details, I'd recommend looking into the code of Spring Data JPA.
Find all references to the Order class and start reading some code.
Have you tried using org.springframework.data.jpa.repository.query.QueryUtils#toOrders ?

Auto generating a String non-primary key value using jpa

Kindly help me to find out a solution to my problem.
I have a property of type String in my entity which is not primary key.
This would act as system generated unique profile id for users in my project.
I want to auto generate this value like a random string of particular size.
Could you please help me to arrive at a solution.
I have tried the #Generator and custom id generator class. but still null is getting inserted to the field in db.
I am using maria db.
Hi you can use the hibernate events.
#PostPersist Executed after the entity manager persist operation is actually executed or cascaded. This call is invoked after the database INSERT is executed.
Starting with Java 5, the UUID class provides a simple means for generating unique ids. The identifiers generated by UUID are actually universally unique identifiers.
Please follow the sample example.
public class TestModel {
#Column("column_name")
private String uid;
//setter and getter for uid
#PrePersist
protected void onCreate() {
// set the uid
setUid(java.util.UUID.randomUUID());
}
}
Please find the below link for more information on #PrePersist.
https://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html

Spring Data JPA finder for dynamic fields as Map

My requirement is to have few custom fields in the domain objects. These fields may vary as per the clients.
We are using Spring Data JPA to execute finders. Spring data implicitly provides finders for static fields of the domain and can also handle finders for the fields in the object graph.
I want to know if there is a way to find data on the custom fields? Can someone suggest me a strategy to achieve the same. Below is the sample of my domain class.
public class Employee{
private String name;
private String age;
private Map customeFields; (May vary as per client)
}
I was thinking of overriding QueryLookupStrategy and create my CustomJpaQuery on lines of PartTreeJpaQuery to achieve it. Is there any better approach? Does spring data jpa provides an easy mechanism to override query creation mechanism?
If you are using hibernate (not sure about other JPA implementations) you may add methods with #Query annotations like this:
#Query("select e from Employee as e where e.customeFields[:key] = :value")
List<Employee> findSomeHow(#Param("key") String key, #Param("value") String value)

JPA: User-Entity contains another User-Entity

In my domain model i have a user entity, which contains another user (composite pattern). When i want to persist the user, i get an error which says something like "Data too long for column...". This happens because the contained user is tried to be stored as a BLOB. I want the ID of the contained user to be stored - not the whole object as a BLOB.
What kind of annotation must i user in the case? The cardinality is 1 : 0..1 - so a user can contain another user.
here is the code ...
#Entity
#Table(name="flex_app_user")
public class User implements Serializable {
private User client;
public User(){
}
#OneToOne
public User getClient() {
return client;
}
}
... and the problem resulted by a change in the datamodel. The correct annotation is OneToOne. And everything works fine.
kind regards,
Jochen
The annotation must be #OneToOne.
As you are using the composite pattern can you use (fetch=FetchType.LAZY) on the relation ship used?