[hibernate-dev] HHH-11791

Gunnar Morling gunnar at hibernate.org
Tue Jun 13 04:06:45 EDT 2017


2017-06-13 7:54 GMT+02:00 Christian Beikov <christian.beikov at gmail.com>:
> Hi,
>
> this might work for a limited set of use cases, but what exactly are you
> expecting from that approach? Performance might be a bit better, but
> that's probably negligible. Apart from that, I only see "encapsulation"
> or "ease of use with other languages" being your argument. Is that
> correct, or are there other reasons why you think constructor injection
> is a good fit here?

I've always had wished for such feature for read-only entities which
could have final fields then.

>
> As soon as you have circular references between entities, you need a
> hybrid approach with setters for some attributes. How would you do lazy
> initialization of entities when some fields don't have a setter?
>
> I could imagine that a constructor is annotated with a marker annotation
> to make it selectable for this kind of hydration and allow the
> parameters of that constructor to be annotated to bind them to entity
> attributes.

The JDK already has an annotation for linking constructor parameters
to bean properties: java.beans.ConstructorProperties. Still might be
better to have a separate one to avoid the dependency to the
java.beans package (and module in terms of Java 9/JPMS).

> By default, the parameter names could be made use of to
> avoid cluttering code. With that information, you can select the
> constructor at boot time for entity types. After all, we know what kind
> of SQL is generated, it's based on the field metadata, so no need for
> the runtime overhead.
>
> I don't know what others think, but when thinking about a possible
> implementation, this seems like a real deep cut that touches many places.
>
>
> Mit freundlichen Grüßen,
> ------------------------------------------------------------------------
> *Christian Beikov*
> Am 12.06.2017 um 23:47 schrieb Christian Bongiorno:
>> To work, yes. This would be an optional means of injecting. I was thinking
>> some code like this (very very rough):
>>
>> public void prep(DataSource source)
>>      throws SQLException, NoSuchMethodException,
>> IllegalAccessException, InvocationTargetException,
>> InstantiationException {
>>
>>    ResultSet resultSet = source.getConnection().createStatement()
>>        .executeQuery("select * from User where false");
>>    ResultSetMetaData metaData = resultSet.getMetaData();
>>    Set<String> columnNames = new HashSet<>();
>>
>>    for(int i = 1; i < metaData.getColumnCount(); i++) {
>>      columnNames.add(metaData.getColumnName(i));
>>
>>    }
>>
>>    Constructor<?> toUse = Arrays.stream(User.class.getDeclaredConstructors())
>>        .filter(c -> c.getParameterCount() == columnNames.size())
>>        .filter(ctr -> Arrays.stream(ctr.getParameters()).map(Parameter::getName)
>>            .allMatch(columnNames::contains)).findFirst().orElse(User.class.getConstructor());
>>
>>    Object entity = null;
>>    if(toUse != User.class.getConstructor()) {// means we found a
>> matching constructor
>>      Object[] input = new Object[toUse.getParameterCount()];
>>      int i = 0;
>>      for (Parameter parameter : toUse.getParameters()) {
>>        input[i++] = resultSet.getObject(parameter.getName());
>>      }
>>      entity = toUse.newInstance(input);
>>    }
>>    else {
>>      entity = toUse.newInstance();
>>    }
>> }
>>
>>
>> One question that comes up is which data set is the master of the match?
>>
>> Do we "Select the constructor that matches the ResultSet?" or "Do we
>> select the result set that matches the constructor?"
>>
>> Another thought is to use the existing field selection logic (find
>> properties on the Class) and then look for the matching constructor; which
>> is a very common paradigm.
>>
>> Finally: An annotation specifically indicating this might also be in order.
>>
>> Just getting the discussion started
>>
>>
>> On Mon, Jun 12, 2017 at 1:41 PM Vlad Mihalcea <mihalcea.vlad at gmail.com>
>> wrote:
>>
>>> Hi,
>>>
>>> Wouldn't that require all entities be compiled with?
>>>
>>> javac -parameters
>>>
>>> Vlad
>>>
>>> On Mon, Jun 12, 2017 at 10:19 PM, Christian Bongiorno <
>>> christian.bongiorno at gmail.com> wrote:
>>>
>>>> Now that java 8 supports named parameters it becomes possible (potentially
>>>> preferrable) to use constructor injection instead of circumventing
>>>> encapsulation to set values on private fields.
>>>>
>>>> This shows itself as a potential win when integrating with Kotlin with
>>>> disallows the circumvention quite forcefully. Meaning: without constructor
>>>> injection the object needs setters. And, if it has setters then it's
>>>> mutable which is against best practices.
>>>>
>>>> I propose optionally using constructor injection when marshalling an
>>>> object
>>>> from data sources in a DB. I am willing to make the changes if I know they
>>>> can/will be incorporated.
>>>>
>>>> Thoughts? Here is the ticket
>>>> https://hibernate.atlassian.net/browse/HHH-11791
>>>>
>>> _______________________________________________
>>>> 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
>
> _______________________________________________
> 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