jsr338-experts@jpa-spec.java.net

[jsr338-experts] Re: proposal : _at_Entity on interfaces

From: Oliver Gierke <ogierke_at_vmware.com>
Date: Mon, 12 Mar 2012 09:57:52 -0700

I fear we get into a philosophical discussion here. Objects have state *and* behavior, which is what especially proponents of Domain Driven Design emphasize. Why should JPA get in the way of using objects this way? I always considered JPA an API to allow mapping objects onto a relational store, not creating Java representations of data tables.

Cheers,
Ollie

Am 12.03.2012 um 17:44 schrieb Pinaki Poddar:

>>> Let me first say that I don't like the model of interfaces on entities.
> ++1
>
> The notion of interface in Java and type that has persistent state just do
> not mix.
> The "contract:" of interface is not a state-oriented contract.
> Trying to mix them will not be a step in a right direction.
>
>
> Regards --
>
> Pinaki Poddar
> Chair, Apache OpenJPA Project http://openjpa.apache.org/
> JPA Expert Group Member
> Application & Integration Middleware
>
>
>
>
>
>
>
>
> From: michael keith <michael.keith_at_oracle.com>
> To: jsr338-experts_at_jpa-spec.java.net
> Cc: Matthew Adams <matthew_at_matthewadams.me>, Bernd Müller
> <bernd.mueller_at_ostfalia.de>
> Date: 03/12/2012 04:39 AM
> Subject: [jsr338-experts] Re: proposal : @Entity on interfaces
>
>
>
> I would really prefer we not go down this path...
>
> -Mike
>
> On 12/03/2012 1:31 AM, Matthew Adams wrote:
>> If we choose to take this on, we could let users express simply
>> through simple java "implements" statements which persistent
>> interfaces a given class implements, and we could allow persistent
>> fields of persistent interface types and persistent collections of
>> interfaces types, as well as queries through them.
>>
>> @Entity
>> // or @MappedSuperclass?
>> // or new @EntityInterface?
>> public interface Employee {
>>
>> // default mapping info allowed here?
>> String getEmployeeNumber();
>> }
>> =====
>> @Entity
>> public class Person
>> implements Employee { /* no addl metadata needed -- implements is
>> sufficient */
>>
>> private String employeeNumber;
>>
>> @Column(name="emp_num")
>> public String getEmployeeNumber() { return employeeNumber; }
>> public String setEmployeeNumber(@NotNull String employeeNumber) {
>> this.employeeNumber = employeeNumber; }
>> }
>> ====
>> @Entity
>> public class Corporation {
>>
>> @OneToMany
>> @AllowedClasses({Person.class, Contractor.class})
>> private List<Employee> employees;
>>
>> @OneToOne
>> @AllowedClasses(Person.class)
>> private Employee president;
>>
>> /* Note:
>> Any assignment of a class other than those whitelisted in
>> @AllowedClasses would
>> cause the JPA implementation to throw ClassCastException
>> */
>> }
>> /*
>> @AllowedClasses could also be an attribute of relationship annotations
>> instead of its own annotation.
>> */
>> =====
>>
>> The hard part, IMHO, is portably mapping them. Wherever you have a
>> reference to a persistent interface, you also need at the point the
>> class of the implementation. Further, I would say that persistent
>> interfaces could only be mapped using property access, as interfaces
>> have no instance fields.
>>
>> One possibility is to allow the use of persistent interfaces, but just
>> say that their mappings are not portable. It would be a nontrivial
>> body of work to bite off the additional specification of portably
>> mapping persistent interfaces.
>>
>> -matthew
>>
>> On Sun, Mar 11, 2012 at 12:27 PM, michael keith
>> <michael.keith_at_oracle.com> wrote:
>>> Let me first say that I don't like the model of interfaces on entities.
> It
>>> is quite rarely requested and when it is, often the user wants multiple
>>> entities to be able to implement the same interface (e.g. polymorphism
> w/o
>>> inheritance) to do something like this:
>>>
>>> public interface Employee { ... }
>>> @Entity public class BusEmployee implements Employee { ... }
>>> @Entity public class TrainEmployee implements Employee { ... }
>>>
>>> and then in some entity:
>>>
>>> @Entity public class TranportationBureau {
>>> ...
>>> @ManyToOne
>>> Employee empOfTheMonth;
>>> }
>>>
>>> The feature being proposed, if I understood it correctly, would not
> support
>>> this.
>>>
>>> Having said that, if we think that aliasing is one of those things that
>>> could stop large companies from using JPA we might decide to close our
> eyes,
>>> hold our noses and go ahead and add some kind of support.
>>>
>>> While I understood and sympathized with the reasons why Steve first
>>> suggested that the annotation be on the interface (to facilitate
>>> interface-to-single-entity enforcement) I tend to agree with Oliver and
>>> Bernd that it would make more sense to just add an "alias" element to
> the
>>> @Entity annotation and continue to apply it to the impl class. It would
> be
>>> the responsibility of the provider to disallow two entities from
> creating an
>>> alias to the same class.
>>>
>>> Example:
>>>
>>> @Entity(alias=Employee.class)
>>> public class EmployeeImpl implements Employee {
>>> // mappings ...
>>> }
>>>
>>> Where does one draw the line? Would we assume that a single alias is
> enough
>>> and that an entity would not be allowed to specify a Set? For example,
> that
>>> we would not need to support something like:
>>>
>>> @Entity(aliases={Employee.class, Worker.class}) ... or ...
>>> @Entity(aliasInterfaces=true)
>>> public class EmployeeImpl implements Employee, Worker {
>>> // mappings ...
>>> }
>>>
>>> -Mike
>>>
>>>
>>> On 11/03/2012 12:23 PM, Bernd Müller wrote:
>>>> I think, this would make many things more complex to specify in a
>>>> consistent way.
>>>>
>>>> In general, interfaces are a way to describe contracts in an
>>>> implementation independent way and therefore should be as abstract
>>>> as possible. JPA is a mapping between VM-objects and databases and
>>>> therefore as close as possible to the implementation level.
>>>> Here I see some problems from a conceptual point of view.
>>>>
>>>> I also see many problems in practice. How to map fields in classes,
>>>> which are eventually named different than the annotated getter in the
>>>> interface? How to map interface hierarchies with multiple super
>>>> interfaces to eventually DIFFERENT class hierarchies with
>>>> single inheritance? There are more, I think.
>>>>
>>>> We have to balance if it's worth to get such new problems which have to
>>>> be resolved in the spec and on the other hand the benefit is less
>>>> typing (how much?).
>>>>
>>>>
>>>> Bernd
>>>>
>>>>
>>>> Am 09.03.2012 19:04, schrieb Steve Ebersole:
>>>>> I'd like to propose that JPA 2.1 allow @Entity on Java interfaces not
>>>>> just classes. The main reason is typing in spec contracts. For
> domain
>>>>> models that leverage interfaces, it is usually desirable to deal with
>>>>> the interfaces over the implementation classes. For example, such
>>>>> applications would generally prefer to attempt to load or get a
>>>>> reference to an instance based on the interface name as opposed to the
>>>>> class name. E.g.
>>>>>
>>>>> public interface Person {
>>>>> ...
>>>>> }
>>>>>
>>>>> @Entity
>>>>> public class PersonImpl implements Person {
>>>>> ...
>>>>> }
>>>>>
>>>>> EntityManager em = ...;
>>>>> Person p = em.find( Person.class, theKey );
>>>>>
>>>>> But this does not work today in a portable manner. To work in the
> most
>>>>> portable manner, I think the @Entity annotated interface also would
> need
>>>>> to name the "persistent implementation class":
>>>>>
>>>>> @Entity( impl = PersonImpl.class )
>>>>> public interface Person {
>>>>> ...
>>>>> }
>>>>>
>>>>> public class PersonImpl implements Person {
>>>>> ...
>>>>> }
>>>>>
>>>>> It could be up to each provider whether or not to support @Entity on
> an
>>>>> interface that did not specify a "persistent implementation class".
>>>>>
>>>>> Another way to look at this is as basically "aliasing" the entity type
>>>>> metadata using the interface name instead of the implementation class
>>>>> name.
>>>>>
>>>>> -Steve
>>>>
>>>>
>>
>>
>
>
>

-- 
/**
 * @author Oliver Gierke - Senior Member Technical Staff
 *
 * @param email ogierke_at_vmware.com
 * @param phone +49-351-30929001
 * @param fax   +49-351-418898439
 * @param skype einsdreizehn
 * @see http://www.olivergierke.de
 */