[hibernate-dev] HHH-11791

Sanne Grinovero sanne at hibernate.org
Tue Jun 13 04:13:57 EDT 2017


On 13 June 2017 at 09:06, Gunnar Morling <gunnar at hibernate.org> wrote:
> 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.

+1 same here.

Having all entities immutable defeats the purpose of managing
entities, so I'm not sold on the "against best practices" reasoning
but it would be great to be able to opt-in for this on selected
entities.

In future we might want to mandate using this technique for all
immutable & readonly entities, so that caching integrations can
benefit from it?

Thanks!
Sanne

>>
>> 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
>
> _______________________________________________
> 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