2017-06-13 7:54 GMT+02:00 Christian Beikov <christian.bei...@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.v...@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.bongio...@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@lists.jboss.org >>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev >>>> >>> >> _______________________________________________ >> hibernate-dev mailing list >> hibernate-dev@lists.jboss.org >> https://lists.jboss.org/mailman/listinfo/hibernate-dev > > _______________________________________________ > hibernate-dev mailing list > hibernate-dev@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/hibernate-dev _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev