JPA inheritance alternative for SINGLE_TABLE? - java

AppEngine only supports "TABLE_PER_CLASS" and "MAPPED_SUPERCLASS" for JPA inheritance.
Unfortunately "JOINED" and especially "SINGLE_TABLE" are not supported.
I'm wondering what the best alternative is to implement a SINGLE_TABLE alternative?
My only requirements are:
1) Have separate classes like AbstractEmployee, InternalEmployee, ExternalExmployee.
2) Being able to run a query over all employees, thus resulting in both InternalEmployee and ExternalEmployee instances.
The only thing I'm thinking off is using a 'big' Employee object containing all fields?
Any other ideas?
PS: vote for proper "SINGLE_TABLE" support via http://code.google.com/p/googleappengine/issues/detail?id=8366

You could in theory use #Embeded and #Embeddable to group related fields into an object. So you would have a class that looks something like.
#Entity
public class Employee {
// all the common employee fields go here
//
// the discriminator column on Employee class lets you be specific in your queries
private Integer type;
#Emebded
private Internal internal; // has the fields that are internal
#Embeded
private External external; // has the fields that are external
equals & hashcode that compare based on the discriminator type and other fields
}

What AppEngine supports and doesn't support is misleading there. AppEngine uses a property store, so any Kind can have any properties. Consequently, in principle, a Kind can contain InternalEmployee and ExternalEmployee "instances". The only thing that AppEngine JPA actually does is store all fields of a class in a single Kind object. That doesn't preclude having subtypes stored in the same Kind (with extra properties for the subtype-specific fields), which is the equivalent of "single-table".
PS, raising some issue on "AppEngine" as a whole won't get any response (look at the rest of issues in there ;-) ), bearing in mind the code affected here is in its own project at http://code.google.com/p/datanucleus-appengine and has its own issue tracker

Related

Best approach for linking diverse entity types in JPA

Short version for the hasty:
There's various tables/entities in my domain model which have the same field (a UUID). There is a table where I need to link rows/instances of such entities to other JPA-managed entities. In other words, the instance of the field in that link table won't be known up-front. The two approaches I can think of are:
Use an abstract entity and a TABLE_PER_CLASS strategy, or
use an #MappedSuperClass store the class name of the instance in the link table as well, or something similar that lets me define logic for getting the actual instance from the right table.
Both have advantages and disadvantages in terms of complexity and performance. Which do you believe to be best, is there maybe a third option, or have you tried something like this in the past and would advice/strongly warn against?
Long version in case you want more background:
I have a database/object model wherein many types have a common field: a universally unique identifier (UUID). The reason for this is that instances of these types can be subject to changes. The changes follow the command model and their data can be encapsulated and itself persisted. Let's call such a change a "mutation". It must be possible to find out which mutations exist in the database for any given entity, and vice-versa, on which entity a stored mutation operates.
Take the following entities with UUIDs as an (extremely simplified) example:
To store the "mutations", we use a table/entity called MutationHolder. To link a mutation to its target entity, there's a MutationEntityLink. The only reason this data isn't directly on the MutationHolder is because there can be direct or indirect links, but that's of little importance here so I left it out:
The question comes down to how I can model the entity field in MutationEntityLink. There are two approaches I can think of.
The first is to make an abstract #Entity annotated class with the UUID field. Customer, Contract and Address would extend it. So it is a TABLE_PER_CLASS strategy. I assume that I could use this as a type for the entity field, although I'm not certain. However, I fear this might have a serious performance penalty since JPA would need to query many tables to find the actual instance.
The second is to simply use #MappedSuperClass and just store the UUID for an entity in the entity field of MutationEntityLink. In order to get the actual entity with that UUID, I'd have to solve it programmatically. Adding an additional column with the class name of the entity, or something else that allows me to identify it or paste it in a JPQL query would do. This requires more work but seems more efficient. I'm not averse to coding some utility classes or doing some reflection/custom annotation work if needed.
My question is which of these approaches seems best? Alternatively, you might have a better suggestion, or notice I'm missing something; for example, maybe there's a way to add a type column even with TABLE_PER_CLASS inheritance to point JPA to the right table? Perhaps you've tried something like this and want to warn me about numerous issues that would arise.
Some additional info:
We create the database schema, so we can add whatever we want.
A single table inheritance strategy isn't an option. The tables must remain distinct. For the same reason, joined inheritance doesn't seem a good fit either.
The JPA provider is Hibernate and using things that are not part of the JPA standard isn't an issue.
If the entities don't have anything in common besides having a uuid I'd use the second approach you describe: use MappedSuperclass. Making the common superclass an entity would prevent you to use a different inheritance strategy if needed, would require a table for that super entity even if no instances exist and from a business point of view it's just wrong.
The link itself could be implemented in multiple ways, e.g. you could subclass MutationEntityLink for each entity to map (e.g. CustomerMutationEntityLink etc.) or do as you described it, i.e. only store the uuid as well as some discriminator/type information and resolve programatically (we're using that approach for something similar btw.).
You need to use #MappedSuperclass while inheriting associations/methods/properties whereas TABLE_PER_CLASS is generally used when you have entity and sub-entities. If there are entities having an association with the base class in the model, then use TABLE_PER_CLASS since the base class behaves like an entity. Otherwise, since the base class would include properties/attributes and methods which are general to such entities not related to each other, using #MappedSuperclass would be a better idea
Example1: You need to set alarms for some different activities like "take medicine", "call mom", "go to doctor" etc. The content of the alarm message does not matter, you will need a reminder. So use TABLE_PER_CLASS since alarm message, which is your base class is like an entity here.
Example2: Assume the base class AbstractDomainObject enables you to create login ID, loginName, creation/modification date for each object where no entity has an association with the base class, you will need to specify the association for the sake of clearing later, like "Company","University" etc. In this situation, using #MappedSuperclass would be better.

How to use reflection to retrieve private variable property from JPA objects

One of my goals is to create an engine that will set values in pojo object from JPA objects dynamically using reflection. One of the matching criteria is, that the field names should match.
I was successfully able to implement this for two pojo objects. But when I tried using JPA objects as one of the object parameter, it didn't work. Based on my research I found out that the method Class.getDeclaredFields() , does not give me the name of the field but the getter/setter method name of member variable for JPA objects.
Can anyone please give me a lead or direction as in where/what should I look to accomplish this task?
JPA providers will often use dynamic proxy classes of your concrete JPA classes, so you have no guarantee of the field names in the proxy. The only guarantee about a proxy is that the methods are the same. Use a debugger to inspect the runtime class of the JPA class instances that you're trying to use and you'll see the problem.
The best you'll be able to do is use reflection to call methods on JPA-returned objects.
All that aside, I don't really see why you'd need to POJO-ify an entity class anyway, since an entity is primarily an annotated... POJO.
One of the matching criteria is, that the field names should match.
I think that this is the root of your problem. There is simply no guarantee that a Java object's field names will match the names of getters and setters ... or anything else. If you make this assumption, you will run into cases where is doesn't work.
The best solution is to simply not use this approach. Make it a requirement that the Pojo classes conform to the JavaBeans spec and rely on the setters to set the properties. This is likely to work more often than making assumptions about (private) field names.
In fact, the state of a generic JPA object implemented using a dynamic proxies could well be held in a hash map. Those fields you can see could simply be constants used for something else.

Does it make sense to use JPA inheritance as a way to get different method implementations?

So, I have been working on familiarizing myself with JPA's inheritance features and have really liked them so far. One thing that occurred to me recently is that they could actually be used for something other than just retrieving data. Given that it can get subclasses based on a discriminator value, inheritance is actually a convenient way to transform configuration fields into implementations. Being in that stage where my knowledge-to-experience ratio is in the 'just enough to be dangerous/not enough to always realize it zone', I thought it might be best to ask if this was a good idea.
Take this example with a PRODUCT and BILLTYPE table.
Product:
int Id
int billtypeid
Billtype:
int id
varchar[15] description
Billtype is simply a billing strategy for the product (We'll say some orders may be billed by weight, while others could just be billed by case). Each bill type will require the use of different methods during the invoicing process. The Billtype table will likely only have a handful of entries, and shouldn't grow to be very large.
Would it make sense to use inheritance to subclass an abstract Billtype entity that also defines an interface for the different methods the invoice code will need? Something like this:
#Entity
#DiscriminatorColumn("description")
public abstract class BillType {
// Getters, setters
// Abstract methods that could be used elsewhere - ex:
// BigDecimal calculateInvVal(...)
}
#Entity
#DiscriminatorValue("by case")
public class CaseBillType extends BillType {
// Implementation of calculateInvVal - now when invoicing code needs this method,
// the right one is always associated with the current product!
}
This provides a convenient way to associate behaviors with fields in the database that represent configuration data, but mixes business code with entities (which, by most accounts, is very very naughty). There could be a design pattern to fix this issue that I am missing from my repertoire, but I'd really like to avoid having to write lots of, "if bill type is this, get this subclass, if bill type is this, etc" code.
What I am looking for from an answer is an explanation of potential drawbacks to this technique I may not be seeing that would justify looking for another solution to this problem.
It's useful to link a product with a BillType entity if it's possible to add, remove and modify bill types at runtime without any need to rebuild and redeploy a new version of the application. This is not the case with your example.
So if what you have is a static set of bill types, each defining a static behavior encapsulated by the BillType subclass, you could simply have a BillType enum instead. Each instance of this enum defining its own behavior. You don't need an entity hierarchy and an additional table for this.
The code to calculate the InVal in the Product entity would be exactly the same:
BigDecimal computeInVal() {
billType.calculateInVal(this);
}
The code to get all the bill types would be
return BillType.values();
And instead of the following code to associate a bill type to a product:
product.setBillType(em.find(BillType.class, ID_OF_CASE_BILL_TYPE));
you would simply have
product.setBillType(BillType.BY_CASE);

Persisting a Map<String,String> in ORMLite without resorting to DataType.SERIALIZABLE?

I've got a relatively simple class that is primarily backed by a Map<String,String>. I'd like to persist this class and be able search within the keys within the map. Based on this Stack Overflow question I get the feeling that Maps can only be persisted as a serialized blob.
I also see on the ORMLite website the following:
public class Account {
…
#ForeignCollectionField(eager = false)
ForeignCollection<Order> orders;
…
}
In the above example, the #ForeignCollectionField annotation marks
that the orders field is a collection of the orders that match the
account. The field type of orders must be either ForeignCollection
or Collection<T> - no other collections are supported. The
#ForeignCollectionField annotation supports the following fields:
Based on the above I get the impression that what I want isn't possible, but I thought I'd check here to be sure. I have it persisted in Hibernate, but I'd rather use something lighter like ORMLite!
One pretty easy solution is to have the getters and setters work with a JSONObject behind the scenes, and putting that object as a String in the database.
But then again, JSON isn't part of java-out-of-the-box so this may feel unneccesary if you're not using it anyway.
Yeah, there is no way in ORMLite to persist a Map. Keeping with the KISS principle, only the simple Collection class is supported. Set and Map have a lot more interface weight to them and will probably never be supported.
I don't have any super great work arounds for you. You could obviously use ForeignCollection and then have a local Map field that you create when you need to access the collection that way. Maybe an addOrder() method that would add it to the ForeignCollection and the Map.

Extending JPA entity data at runtime

I need to allow client users to extend the data contained by a JPA entity at runtime. In other words I need to add a virtual column to the entity table at runtime. This virtual column will only be applicable to certain data rows and there could possibly be quite a few of these virtual columns. As such I don't want to create an actual additional column in the database, but rather I want to make use of additional entities that represent these virtual columns.
As an example, consider the following situation. I have a Company entity which has a field labelled Owner, which contains a reference to the Owner of the Company. At runtime a client user decides that all Companies that belong to a specific Owner should have the extra field labelled ContactDetails.
My preliminary design uses two additional entities to accomplish this. The first basically represents the virtual column and contains information such as the field name and type of value expected. The other represents the actual data and connects an entity row to a virtual column. For example, the first entity might contain the data "ContactDetails" while the second entity contains say "555-5555."
Is this the right way to go about doing this? Is there a better alternative? Also, what would be the easiest way to automatically load this data when the original entity is loaded? I want my DAO call to return the entity together with its extensions.
EDIT: I changed the example from a field labelled Type which could be a Partner or a Customer to the present version as it was confusing.
Perhaps a simpler alternative could be to add a CLOB column to each Company and store the extensions as an XML. There is a different set of tradeoffs here compared to your solution but as long as the extra data doesn't need to be SQL accessible (no indexes, fkeys and so on) it will probably be simple than what you do now.
It also means that if you have some fancy logic regarding the extra data you would need to implement it differently. For example if you need a list of all possible extension types you would have to maintain it separately. Or if you need searching capabilities (find customer by phone number) you will require lucene or similar solution.
I can elaborate more if you are interested.
EDIT:
To enable searching you would want something like lucene which is a great engine for doing free text search on arbitrary data. There is also hibernate-search which integrates lucene directly with hibernate using annotations and such - I haven't used it but I heard good things about it.
For fetching/writing/accessing data you are basically dealing with XML so any XML technique should apply. The best approach really depends on the actual content and how it is going to be used. I would suggest looking into XPath for data access, and maybe look into defining your own hibernate usertype so that all the access is encapsulated into a class and not just plain String.
I've run into more problems than I hoped I would and as such I decided to dumb down the requirements for my first iteration. I'm currently trying to allow such Extensions only on the entire Company entity, in other words, I'm dropping the whole Owner requirement. So the problem could be rephrased as "How can I add virtual columns (entries in another entity that act like an additional column) to an entity at runtime?"
My current implementation is as follow (irrelevant parts filtered out):
#Entity
class Company {
// The set of Extension definitions, for example "Location"
#Transient
public Set<Extension> getExtensions { .. }
// The actual entry, for example "Atlanta"
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "companyId")
public Set<ExtensionEntry> getExtensionEntries { .. }
}
#Entity
class Extension {
public String getLabel() { .. }
public ValueType getValueType() { .. } // String, Boolean, Date, etc.
}
#Entity
class ExtensionEntry {
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "extensionId")
public Extension getExtension() { .. }
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "companyId", insertable = false, updatable = false)
public Company getCompany() { .. }
public String getValueAsString() { .. }
}
The implementation as is allows me to load a Company entity and Hibernate will ensure that all its ExtensionEntries are also loaded and that I can access the Extensions corresponding to those ExtensionEntries. In other words, if I wanted to, for example, display this additional information on a web page, I could access all of the required information as follow:
Company company = findCompany();
for (ExtensionEntry extensionEntry : company.getExtensionEntries()) {
String label = extensionEntry.getExtension().getLabel();
String value = extensionEntry.getValueAsString();
}
There are a number of problems with this, however. Firstly, when using FetchType.EAGER with an #OneToMany, Hibernate uses an outer join and as such will return duplicate Companies (one for each ExtensionEntry). This can be solved by using Criteria.DISTINCT_ROOT_ENTITY, but that in turn will cause errors in my pagination and as such is an unacceptable answer. The alternative is to change the FetchType to LAZY, but that means that I will always "manually" have to load ExtensionEntries. As far as I understand, if, for example, I loaded a List of 100 Companies, I'd have to loop over and query each of those, generating a 100 SQL statements which isn't acceptable performance-wise.
The other problem which I have is that ideally I'd like to load all the Extensions whenever a Company is loaded. With that I mean that I'd like that #Transient getter named getExtensions() to return all the Extensions for any Company. The problem here is that there is no foreign key relation between Company and Extension, as Extension isn't applicable to any single Company instance, but rather to all of them. Currently I can get past that with code like I present below, but this will not work when accessing referenced entities (if for example I have an entity Employee which has a reference to Company, the Company which I retrieve through employee.getCompany() won't have the Extensions loaded):
List<Company> companies = findAllCompanies();
List<Extension> extensions = findAllExtensions();
for (Company company : companies) {
// Extensions are the same for all Companies, but I need them client side
company.setExtensions(extensions);
}
So that's were I'm at currently, and I have no idea how to proceed in order to get past these problems. I'm thinking that my entire design might be flawed, but I'm unsure of how else to try and approach it.
Any and all ideas and suggestions are welcome!
The example with Company, Partner, and Customer is actually good application for polymorphism which is supported by means of inheritance with JPA: you will have one the following 3 strategies to choose from: single table, table per class, and joined. Your description sounds more like joined strategy but not necessarily.
You may also consider just one-to-one( or zero) relationship instead. Then you will need to have such relationship for each value of your virtual column since its values represent different entities. Hence, you'll have a relationship with Partner entity and another relationship with Customer entity and either, both or none can be null.
Use pattern decorator and hide your entity inside decoratorClass bye
Using EAV pattern is IMHO bad choice, because of performance problems and problems with reporting (many joins). Digging for solution I've found something else here: http://www.infoq.com/articles/hibernate-custom-fields

Categories