[hibernate-dev] HHH-9440 Support for Java 8: parameter names

Lovro Pandzic lovro.pandzic at gmail.com
Mon Mar 28 14:24:18 EDT 2016


>
>  I am confused how you are "mind mapping" PreparedStatement parameters and
> entity construction into the same conversation.  We are not instantiating
> entities based on PreparedStatement parameters....
>

I'm not sure I understand you, I haven't mentioned PreparedStatement
parameters anywhere.


> What you propose is to delay the entity instantiation and create the
> entity instance from after we have the hydrated state.


Yes, the requirement for this to work is that before calling constructor
you have all arguments and target parameter names available.

The property names that might be used as constructor arguments should
> probably be annotated with a @ConstructorArg annotation and possibly
> specify the argument order in the construction newInstance(args)
> invocation.
>

It can be done without it, like in the jackson module I mentioned earlier.
After the arguments and target parameter names are available, you match the
arguments against parameters with the constructor parameter names available
via Parameter names API. No annotations, no additional configuration except
for -parameters to the compiler.
The idea is to be able to do something like:

// id and column definitions are left out on puprose
class Person {

    // mandatory fields
    private final String name;
    private final String surname;
    private final Address address;

    // optional fields
    private String nickname;

    public Person(String name, String surname, Address address) {
        // initialization and other logic
    }

    public String getName() {
        return name;
    }

    public String getSurname() {
        return surname;
    }

    public String getNickname() {

        return nickname;
    }

    public void setNickname(String nickname) {

        this.nickname = nickname;
    }
}

// value type candidate
@Embeddable
public class Address {

    private final String line1;
    private final String line2;

    @Embedded
    private final ZipCode zipCode;

    public Address(String line1, String line2, ZipCode zipCode) {
        // initialization and other logic
    }
}

ZipCode is left out but you get the idea. Target of this proposal are not
just entities but embeddables too.

On Mon, Mar 28, 2016 at 3:01 PM, Steve Ebersole <steve at hibernate.org> wrote:

> JPA says that portable applications (portable across JPA providers) should
> have  default constructor.  Every provider supports things beyond the
> spec.  Heck JPA also says that getters and setters need to be public, but
> we don't enforce that either.
>
> On Mon, Mar 28, 2016 at 7:27 AM Vlad Mihalcea <mihalcea.vlad at gmail.com>
> wrote:
>
>> Nowadays the entity instantiation and data population is done like that:
>>
>> final Object object;
>> if ( optionalObjectKey != null && key.equals( optionalObjectKey ) ) {
>>     //its the given optional object
>>     object = optionalObject;
>> }
>> else {
>>     // instantiate a new instance
>>     object = session.instantiate( instanceClass, key.getIdentifier() );
>> }
>>
>> //need to hydrate it.
>>
>> // grab its state from the ResultSet and keep it in the Session
>> // (but don't yet initialize the object itself)
>> // note that we acquire LockMode.READ even if it was not requested
>> LockMode acquiredLockMode = lockMode == LockMode.NONE ? LockMode.READ :
>> lockMode;
>> loadFromResultSet(
>>         rs,
>>         i,
>>         object,
>>         instanceClass,
>>         key,
>>         rowIdAlias,
>>         acquiredLockMode,
>>         persister,
>>         session
>> );
>>
>> What you propose is to delay the entity instantiation and create the
>> entity instance from after we have the hydrated state.
>> That's also the case for the second-level caching entries which must
>> "hydrate" an object instance.
>>
>> The first problem is that JPA demands the default no-arg constructor:
>>
>> "The entity class must have a no-arg constructor. The entity class may
>> have other constructors as well. The no-arg constructor must be public or
>> protected."
>>
>> The property names that might be used as constructor arguments should
>> probably be annotated with a @ConstructorArg annotation and possibly
>> specify the argument order in the construction newInstance(args) invocation.
>>
>> So, there are a lot of things to consider when implementing such a
>> feature.
>>
>> Vlad
>>
>> On Mon, Mar 28, 2016 at 3:05 PM, Steve Ebersole <steve at hibernate.org>
>> wrote:
>>
>>> Commented on the Jira.
>>>
>>> I am confused how you are "mind mapping" PreparedStatement parameters and
>>> entity construction into the same conversation.  We are not instantiating
>>> entities based on PreparedStatement parameters....
>>>
>>> On Fri, Mar 18, 2016 at 2:32 AM Lovro Pandzic <lovro.pandzic at gmail.com>
>>> wrote:
>>>
>>> > Hello,
>>> >
>>> > I'd like to discuss issue HHH-9440.
>>> >
>>> > Basic idea behind this issue is that we try to and eliminate the
>>> > requirement for no arg constructor on entities or at least weaken that
>>> > requirement to specific cases.
>>> > Construction from both the user code and the hibernate itself would go
>>> > through user specified constructors.
>>> > This would enable use cases like enforcing invariants in constructors,
>>> > immutable entities and in the long run, maybe even support for value
>>> types
>>> > coming in Java 10 that, at least for now, we know will be immutable and
>>> > won't have a no arg constructor.
>>> >
>>> > By using parameter names and Java 8 API you can, for instance, map
>>> those
>>> > parameter names to fields to find out column mappings and other
>>> information
>>> > required for mapping arguments to parameters.
>>> >
>>> > A similar approach like this is used by jackson-databind with the
>>> > jackson-module-parameter-names (this will soon be integrated into the
>>> > jackson-databind itself). Another example, Spring also uses parameter
>>> names
>>> > to map bean names to parameters in constructors.
>>> >
>>> > There are border cases like the one Steve mentioned in the issue:
>>> >
>>> > > How would you see lazy loading working then?
>>> > >
>>> >
>>> > >From my perspective, there are 2 approaches here:
>>> > - use a library like Objenesis that enables you to construct classes
>>> > without using the constructor
>>> > - document that all entities that are to be proxied must have a no arg
>>> > constructor
>>> >
>>> > What do you guys think?
>>> > _______________________________________________
>>> > hibernate-dev mailing list
>>> > hibernate-dev at lists.jboss.org
>>> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>> >
>>> _______________________________________________
>>> hibernate-dev mailing list
>>> hibernate-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>
>>
>>


More information about the hibernate-dev mailing list