users@jpa-spec.java.net

[jpa-spec users] [jsr338-experts] Re: proposal : _at_Entity on interfaces

From: Steve Ebersole <steve.ebersole_at_redhat.com>
Date: Tue, 13 Mar 2012 15:58:57 -0500

+1000

On Mon 12 Mar 2012 11:57:52 AM CDT, Oliver Gierke wrote:
> 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
>>>>>
>>>>>
>>>
>>>
>>
>>
>>
>