[hibernate-dev] HHH-11791
Christian Beikov
christian.beikov at gmail.com
Tue Jun 13 01:54:42 EDT 2017
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?
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. 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
More information about the hibernate-dev
mailing list