Is it possble to write query at JPA entity property level?
Basically I want to add a property in an entity which is not an actual column and value should computed with query.
Something like:
#Entity
#Table(schema = "quote", name = "QUOTE_SCENARIO")
public class QuoteScenario {
#Query(Select max(Lead_Time) from differentEntity)
private Integer leadTime;
}
No. This is not possible as the query annotation is at the method level. You can try and do this using formula in Hibernate.
Related
In my Kotlin code:
I have an entity class as follows (simplified):
#Entity
data class Person(
) {
#Id val id: String,
val phoneNumber: String
}
I have a spring-data-jpa repository as follows (simplified):
interface PersonRepository: JpaRepository<Person, String> {
#Query(
value = "SELECT p FROM Person p WHERE :#T(com.xyz.PhoneUtils).normalizePhoneNumber(p.phoneNumber)} IN :phoneNumbers")
fun getPersonsByPhoneNumbers(phoneNumbers: Set<String>: Set<Person>): List<Person>
}
Notice the use of an SPEL expression to call a static function on specified class. The function normalizes phone numbers to a standard E.164 phone number format. The reason for this complexity is that the Person records may contain phone numbers in non-standard formats but the supplied phoneNumbers via query param phoneNumbers are normalized. To make a comparison I need to normalize the entity attribute phoneNumber within the #Query query expression.
However, I cannot figure out how to use an entity attribute phoneNumber as a function param for the PhoneUtils.normalizePhoneNumber within the SPEL expression. Spring documentation says nothing about using entity attributes within SPEL expressions though it does say how to use query parameters within the SPEL expression.
Is it possible to use entity attribute as a function param within the SPEL expression? If so, how? TIA.
I realize now that since JPQL query is mapped to an SQL query the only way to use a function with an entity attribute as parameter is to have the query be invoked by the database. The solution requires calling Kotlin/Java static method using database-specific methods. For my HSQLDB the following describes how it can be done:
https://hsqldb.org/doc/2.0/guide/sqlroutines-chapt.html#src_jrt_static_methods
Following the guide lines from Domain Driven Design, I try to avoid having one aggregate referencing a different aggregate. Instead, an aggregate should reference another aggregate using the other aggregate's id, for example:
public class Addiction
{
private Addiction(){} //Needed for EF to populate non-simple types
//DrugType belongs to the aggregate,
//inflate when retrieving the Addiction from the db
//EF does not need DrugId for navigation
Drug Drug{get;set;}
//The supplier is not part of the aggregate,
//aggregates only reference eachother using Ids
int SupplierId{get;set;}
//Other properties
}
public class AddictionConfiguration : IEntityTypeConfiguration<Addiction>
{
builder.HasOne(addiction => addiction.Drug); //Works
builder.HasOne("SupplierId") //Does not work.
}
In this (not very realistic) example, Drug is part of the Addiction's aggregate. When loading this entity from the database using EF, it will also inflate the Drug property without me having to specify the DrugId as the foreign key.
However, now I need to get a list of all Addictions and their suppliers by mapping the relevant properties to a Dto. I try to achieve this by using AutoMapper's ProjectTo functionality, e.g.
_mapper.ProjectTo<AddictionDto>(_dbContext.Addictions.Where(x => x.Id > 1));
where AddictionDto is defined as
public class AddictionDto
{
DrugDto Drug {get;set;}
SupplierDto Supplier {get;set;}
//other properties
}
And
public class SupplierDto
{
public int Id {get;set;}
public string Name {get;set;}
}
Automapper correctly loads the Addiction and also the Drug, but I cannot get it to load the Supplier. I've tried all the options of the IEntityTypeConfiguration to tell EF that there is a navigation property, but I cannot get it to work. Does anyone know if is even possible to do what I described above?
I am trying to use nested Mongodb query but it does not work.
It is similar to Spring data mongodb query for subdocument field
But suggestions mentioned there does not work.
Please find my documents below.
#Document
public class Ticket {
#Id
private String id;
#DBRef
#CascadeSave
private Customer customer;
// getters and setters
}
#Document
public class Customer {
#Id
private String id;
private String firstName;
// getters and setters
}
public interface TicketRepository extends MongoRepository<Ticket, String> {
public List<Ticket> findByCustomerFirstName(String firstName);
}
I tried both findByCustomerFirstName and findByCustomer_FirstName but it does not work. Any suggestions ?
These suggestions are right it should work...
Official docs explains it as you did it:http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.query-methods.query-property-expressions
Property expressions can refer only to a direct property of the
managed entity, as shown in the preceding example. At query creation
time you already make sure that the parsed property is a property of
the managed domain class. However, you can also define constraints by
traversing nested properties. Assume a Person has an Address with a
ZipCode. In that case a method name of
List<Person> findByAddressZipCode(ZipCode zipCode);
creates the
property traversal x.address.zipCode
Just one thing, remove #Document from Customer and try it, Mongodb didn't support join queries (I'm not sure if now it does)... so you're document should be Ticket and it must have a embbebed document Customer as a inner object and not in a different document.
I have a table place that contain as column "state" (it is an Enum that can be 'ACTIVE' or 'INACTIVE')
I would like to know if there is a way with JPA2 that when i call placeRepository.findAll() or placeRepository.getOne(id) only select the row in the database that are marked as "ACTIVE" ?
something like this
List<Place> findByStateActiveOnly();
EDIT:
Bonus question:
I'am at the moment refactoring my project to be able to add a place (and other entities) in a pending state. Because I have added an extra column "state" now i have to add to ALL my queries this condition "AND p.state=my.package.State.ACTIVE" like this;
#Query("select p from Place p where p.idPlace = ?1 AND p.state=my.package.State.ACTIVE")
Isn't there a way to tell jpa to automatically select me if the state is ACTIVE ?
Thank you!
With Hibernate, you can try annotating your entity with #Where, something like this
#Entity
#Where(clause = "state = 'ACTIVE'")
public class Place {...}
Do with parameter:
public interface YourRepository ... {
List<Place> findByState(String state);
}
you will invoke like:
List<Place> placeList = youRepository.findByState("ACTIVE");
I have a named native query and I am trying to map it to the return results of the named native query. There is a field that I want to add to my entity that doesn't exist in the table, but it will exist in the return result of the query. I guess this would be the same with a stored proc...
How do you map the return results of a stored proc in JPA?...
How do you even call a stored proc?
here is an example query of what I would like to do...
select d.list_id as LIST_ID, 0 as Parent_ID, d.description from EPCD13.distribution_list d
The Result will be mapped to this entity...
public class DistributionList implements Serializable {
#Id
#Column(name="LIST_ID")
private long listId;
private String description;
private String owner;
private String flag;
#Column(name="PARENT_ID", nullable = true)
private long parentID;
}
parent ID is not in any table in my database. I will also need to use this entity again for other calls, that have nothing to do with this call, and that will not need this parent_id? Is there anything in the JPA standard that will help me out?
If results from database are not required for further manipulation, just for preview, you can consider using database view or result classes constructor expression.
If entities retrieved from database are required for further manipulation, you can make use of multiple select expression and transient fields.
Replace #Column annotation with #Transient annotation over parentID.
After retrieving multiple columns from database, iterate over results and manually set parentID.