Is there a way how to define an entity hierarchy that enables to query just particular subclass? Consider situation below. Let's have abstract Base class that defines common properties and concrete subclasses A and B.
class abstract Base {
...
}
class A extends Base {
...
}
class B extends Base {
...
}
I would like to run for example queries as follows.
To retrieve all entities of type A and B
Base base = this.objectify.load().type(Base.class).list();
To retrieve all entities of type A
Base base = this.objectify.load().type(A.class).list();
To retrieve all entities of type B
Base base = this.objectify.load().type(B.class).list();
Furthermore, we would like to store all such entities as a single type (Base entity) in GAE Datastore.
We tried to use polymorphic hierarchy of related entity classes described here:
https://code.google.com/p/objectify-appengine/wiki/Entities#Polymorphism
But it seems that this is not capable of handling a situation where there are multiple entity subclasses with a common parent.
I don't think Base can be abstract, but this should work:
#Entity
class Base { ... }
#EntitySubclass(index=true)
class A extends Base { ... }
#EntitySubclass(index=true)
class B extends Base { ... }
If you want to be able to query by polymorphic type, you must index the types that you want to query by.
Related
I have a requirement that based on profile I need to inject 2 different classes into DAO layer to perform CRUD operation. Let's say we have class A and Class B for profiles a and b respectively. Now in the DAO layer without using if else condition (As I am using that currently based on the profile, I am using service layer to call 2 different methods 1.saveA(), 2.saveB().) But is there any way to make it more generic and based on profile or either by the class reference I can instantiate different entity as well as JPA Classes? I tried to use
<T extends Parent> T factoryMethod(Class<T> clazz) throws Exception {
return (T) clazz.newInstance();
}
but this also will force me to cast the returned object to a class. I tried creating a parent P for both class A and B. and used them instead but got confused when injecting the entity types to JPARepository.
I tried creating a SimpleJPARepository but didnt worked as there are overridden methods in ARepository and BRepository.
Or,
is there a way I can use the same entity class for 2 different tables? that way it can be solved. for 1 profile I have different sets of columns whereas for 2nd profile I have different columns.
this is how I am expecting: Would it be possible? or, how I am doing now is correct?
public void doStuff(Class<T> class){
GenericRepository repo;
if(class instanceof A){
//use ARepository;
repo = applicationContext.getBean(ARepository);
}else{
//use BRepository;
repo = applicationContext.getBean(BRepository);
}
repo.save(class);
repo.flush();
}
You can create a method utility like following: The key is the class type of the entity and the value is the repository.
Map<Class<? extends Parent>, JpaRepository> repoMapping = new HashMap<>();
#PostConstruct
public void init(){
repoMapping.put(A.class, applicationContext.getBean(ARepository));
repoMapping.put(B.class, applicationContext.getBean(BRepository));
}
public JpaRepository getRepo(Class<? extends Parent> classs){
return repoMapping.get(classs);
}
I have a validator that validates Entities having javax.validation.constraints annotations:
public class EntityValidator {
void validate(Object obj) {
...
}
}
My goal is to make EntityValidator Generic but accept only Entity classes:
public class EntityValidator<E extends ???> {
void validate(E entity) {
...
}
}
The entities are having #Entity annotation and are all in the same package, but none of them have a common parent class.
What is the best practice to connect Entity classes fit to a same type?
The choices I think of:
Entities implement marker interface (eg. Serializable)
Create parent class (eg. BaseEntity) and inherit Entities from it.
Accept classes only with #Entity annotation in validator - not sure it is possible?
Assuming that you want the constraint to be enforced statically, the third option (by annotation) is out.
I'd venture that your best bet would be your own custom marker interface - so that your validation wouldn't interact with other facilities (as it would if you used Serializable,) and so that your hands would be left untied with the inheritance hierarchy.
I would like to create a Spring Data JPA repository with custom behavior, and implement that custom behavior using Specifications. I have gone through the Spring Data JPA documentation for implementing custom behavior in a single repository to set this up, except there is no example of using a Spring Data Specification from within a custom repository. How would one do this, if even possible?
I do not see a way to inject something into the custom implementation that takes a specification. I thought I would be tricky and inject the CRUD repository portion of the repository into the custom portion, but that results in a circular instantiation dependency.
I am not using QueryDSL. Thanks.
I guess the primary source for inspiration could be how SimpleJpaRepository handles specifications. The key spots to have a look at are:
SimpleJpaRepository.getQuery(…) - it's basically creating a CriteriaQuery and bootstraps a select using a JPA Root. Whether the latter applies to your use case is already up to you. I think the former will apply definitely.
SimpleJpaRepository.applySpecificationToCriteria(…) - it basically uses the artifacts produced in getQuery(…) (i.e. the Root and the CriteriaQuery) and applies the given Specification to exactly these artifacts.
this is not using Specification, so not sure if it's relevant to you, but one way that I was able to inject custom behavior is as follows,
Basic structure: as follows
i. create a generic interface for the set of entity classes which are modeled after a generic parent entity. Note, this is optional. In my case I had a need for this hierarchy, but it's not necessary
public interface GenericRepository<T> {
// add any common methods to your entity hierarchy objects,
// so that you don't have to repeat them in each of the children entities
// since you will be extending from this interface
}
ii. Extend a specific repository from generic (step 1) and JPARepository as
public interface MySpecificEntityRepository extends GenericRepository<MySpecificEntity>, JpaRepository<MySpecificEntity, Long> {
// add all methods based on column names, entity graphs or JPQL that you would like to
// have here in addition to what's offered by JpaRepository
}
iii. Use the above repository in your service implementation class
Now, the Service class may look like this,
public interface GenericService<T extends GenericEntity, ID extends Serializable> {
// add specific methods you want to extend to user
}
The generic implementation class can be as follows,
public abstract class GenericServiceImpl<T extends GenericEntity, J extends JpaRepository<T, Long> & GenericRepository<T>> implements GenericService<T, Long> {
// constructor takes in specific repository
public GenericServiceImpl(J genericRepository) {
// save this to local var
}
// using the above repository, specific methods are programmed
}
specific implementation class can be
public class MySpecificEntityServiceImpl extends GenericServiceImpl<MySpecificEntity, MySpecificEntityRepository> implements MySpecificEntityService {
// the specific repository is autowired
#Autowired
public MySpecificEntityServiceImpl(MySpecificEntityRepository genericRepository) {
super(genericRepository);
this.genericRepository = (MySpecificEntityRepository) genericRepository;
}
}
I have a class C extends B. and B extends A. A has an attribute name. I don't want to see name attribute at C class.
How can I do that ignore?
PS: If it is not possible at Java: I am working on a Spring project that uses Apache CXF and has a web service capability. I want to get B type object from client and send C type object to client. Because of my design issues I don't want to change my inheritance mechanism. If there is a way can I ignore name field at C class? I am implementing as first-code style.
You can declare name field in A as private and keep both A and B in same Package.
package A;
Class A {
protected String name;
}
Class B extends A{
// B can access A's attribute
}
package C;
Class C extends B{
// C cannot access name attribute defined in A.
}
And keep C is in a different package.
Please read about composition over inheritance. If you need to hide some elements then probably you do not understood properly the Object Oriented code design.
The example provided by you is too narrow to create any better answer. But what is the point of hiding in C when, you can cast it to A and still use it ?
I have a class C extends B. and B extends A. A has an attribute
name. I don't want to see name attribute at C class.
Based on your edit, you are trying to hide an attribute from a superclass (A) in the serialized representation of one of it's subclasses (C). Assuming you are using JAX-WS/JAX-RS, you can do this by overriding the property in the subclass and applying annotations to mark it as not eligible for serialization. The primary annotation to apply will be the JAXB annotation #XmlTransient. You can also #JsonIgnore the property, if you are providing the option to serialize objects as JSON. Pseudo code shown below:
#XmlRootElement
public class A implements Serializable {
private String name;
// ...
}
#XmlRootElement
public class C extends A {
#Override
#XmlTransient
public String getName() {
return super.getName();
}
}
I'm trying to implement a inheritence relationship between JPA entities.
Borrowing the example from:
http://openjpa.apache.org/builds/1.0.2/apache-openjpa-1.0.2/docs/manual/jpa_overview_mapping_discrim.html
#Entity
#Table(name="SUB", schema="CNTRCT")
#DiscriminatorColumn(name="KIND", discriminatorType=DiscriminatorType.INTEGER)
public abstract class Subscription {
...
}
#Entity(name="Lifetime")
#DiscriminatorValue("2")
public class LifetimeSubscription
extends Subscription {
...
}
}
#Entity(name="Trial")
#DiscriminatorValue("3")
public class TrialSubscription
extends Subscription {
...
}
What I need to be able to do is have an additional entity that catches the rest, something like:
#Entity(name="WildCard")
#DiscriminatorValue(^[23])
public class WildSubscription
extends Subscription {
...
}
Where if it does not match LifetimeSubscription or TrialSubscription it will match WildSubscription.
It actually makes a bit more sense if you think of it where the wild is the superclass, and if there is not a more concrete implementation that fits, use the superclass.
Anyone know of a method of doing this?
Thanks!
The JPA API allows only plain values here, and for a reason: discriminator values are mapped to SQL WHERE:
SELECT ... WHERE kind = 1
If you could specify regular expressions here, it wouldn't be transferable to SQL, as it does not support such constructs.