I have entity with a #Transient field and I am using JPA specification to filter data. I want execute a sub query and assign result to transient field form specification.
#Transient
private Integer delayedDays;
Using #PostLoad and #PrePersist annotations
https://www.baeldung.com/jpa-persisting-enums-in-jpa
https://github.com/aballaci/springboot-jpa-sakila/blob/master/src/main/java/de/ballaci/jpa/domain/Film.java
Related
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 ?
I'm having some trouble trying to figure out how to set up a class that has an #Embedded field that must be fetched lazily. I tried to annotate the field with #Basic(fetch = FetchType.LAZY), but it causes the persistence API to treat the field as a basic type that implements Serializable, so it maps the field to a BYTEA field in the database (postgresql). I tested it on Derby too, and the same happens.
I also tried to annotate the fields of the #Embeddable class individually with #Basic(fetch = FetchType.LAZY) instead of annotating the #Embedded field of the entity that has it. The generated schema is correct in this case, but the fields are fetched eagerly when I load instances of the entity.
My understanding is that the #Basic annotation is used on basic fields/properties only, so the first case is expected. But why the fields of the #Embeddable class are fetched eagerly even if they are annotated with #Basic(fetch = FetchType.LAZY)? Also, I know that the fetch strategy can be specified by the #Basic and relationship annotations, but is there any other way to specify that fields should be fetched lazily? I'm using EclipseLink 2.6, but let me know if the behaviour is different for other versions of EclipseLink or for another provider.
Directly you cant, because of how #Embedded objects work, but by setting attributes in the object it should work.
#Basic(fetch=FetchType.LAZY)
Remember that lazy should be use only on collections or big objects, and that setting fetch type on lazy is only a clue for provider, it doesn't mean that it will always fetch it lazy rather than eager.
I have a MongoRepository class
public interface UserRepository extends MongoRepository<User, Long> {
User findById(Long id);
}
and my Entity pojo looks like this
#Document(collection = "user")
class User {
Long id;
String name;
Department department;
…
}
When I call the findBy method, a User object is returned. I want to know how does Spring Data MongoDB converts DBObject to Java object. I was under the impression that Spring Data MongoDB uses some sort of mapper (Jackson?) under the hood which would call setters/constructors method of the java(Entity) class based on the field names in the class or #Field Annotation. But to my surprise, the setters are never invoked. Only the default constructor is invoked.
Then how does the fields are set? The reason I am asking is if the setters are called, it would give me an option to set some other fields may be.
Thanks
Spring Data defaults to field access as accessor methods can contain additional logic that we don't want to trigger by accident. If that's what you actually want though, you can switch to property access by annotating your class with #AccessType(Type.PROPERTY).
Spring has a entity converter at the subsequent layer below it. It uses reflection to read the type of field, variables and signature. The conversion logic is generic for all data repositories. You can read about the same here
You can also introduce a custom converter be it yours or jackson, an example of it is here
Take a look at MappingMongoConverter class - it has the logic which does all this.
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)
The following JPA query doesn't compile -
SELECT a FROM CUSTOMER a WHERE a.activeCustomer = 'N' AND a.customerInfo.city IN :cityName ORDER BY a.customerId
where the table CUSTOMER in Oracle database has a base type - CUSTOMERINFO which in turn has various values such as -
city
country
This base type CUSTOMERINFO is extended by LOCALBUSINESSCUSTOMERINFO and MNCBUSINESSCUSTOMERINFO and a few others.
I think this may be due to the fact that when I define the column in my entity I define it as follows -
#Entity
#Table(name = "CUSTOMER", schema = "DBA")
#Converter(name="CustomerInfoConvertor", converterClass=CustomerInfoConvertor.class)
public class Customer implements Serializable {
#Basic
#Convert("CustomerInfoConvertor")
#Column(columnDefinition = "CUSTOMERINFO")
private ICustomerInfo customerInfo;
}
I have tried this query using SQL and it works fine but using it from JPA (JPQL) throws compilation error.
Thanks for your help!
You have mapped your customerInfo as a basic, so it is a basic in JPQL.
The column is of an Object object type?
In EclipseLink 2.3 you can map this as an Embeddable and the #Struct annotation, and use an Embedded mapping from the Customer. Does the customer table have other columns or is it a type table? If it is a type table, then use the #Struct to map it.