On 26 March 2014 18:37, Steve Ebersole <st...@hibernate.org> wrote: > My point is that I do not find annotating a getter method with > @Access(FIELD) to be inherently common sense. It really boils down to the > purpose/intent of @Access. If @Access *at the attribute level* is > ultimately *just* indicating how to extract/inject then I think > @Access(FIELD) on the getter does make sense. If @Access *at the attribute > level* also directs where to look for annotations (consistent with @Access > at class/hierarchy-level) then I think @AccessFile needs to be on the field > along with the other annotations, assuming we stay with non-mixed placement > for an attribute.
Here a use case: as convention the team likes to put all annotations on getters, but then for some specific reason a field needs to be configured to have the ORM to use field access. Seems fair enough? Sanne > > So let's decide that first. Since the spec does not say clearly one way or > the other, I guess we have some leeway here. > > https://hibernate.atlassian.net/browse/HHH-9085 (Introduce @IdGetter and > @IdSetter) plays in here as well. > > > > On Wed, Mar 26, 2014 at 11:21 AM, Emmanuel Bernard <emman...@hibernate.org> > wrote: >> >> My take on the spec as always been that I'd rather follow the intent, >> the common sense above the letter. Likewise, I favored user experience >> over spec strict adherence. >> I did clash numerous time with the TCK in these targets but I still >> prefer that over just doing something stupid but spec to the letter. >> (this is general and not specific to that case). >> >> Anyway so my take is pretty much as it was when I first implemented >> @AccessType even if it steps over the spec at the margin. >> BTW I'm also happy if we all decide I made a usability mistake that should >> be fixed. >> >> Emmanuel >> >> On Wed 2014-03-26 11:14, Steve Ebersole wrote: >> > On Wed, Mar 26, 2014 at 10:12 AM, Steve Ebersole >> > <st...@hibernate.org>wrote: >> > >> > > It does violate the spec though, that's the problem: >> > > >> > >> > Well it *could* be read to violate the spec. That's inherently the >> > problem >> > with specs that use unclear wording; they can be read and argued >> > multiple >> > ways. >> > >> > >> > >> > > >> > > "... It is not permitted to specify a field as Access(PROPERTY) or a >> > > property as Access(FIELD)..." >> > > >> > > which imo is exactly what this is doing (specifying a property as >> > > FIELD): >> > > >> > > @Id >> > > @GeneratedValue >> > > @Access(AccessType.FIELD) >> > > public long getId() { >> > > return id; >> > > } >> > > >> > > >> > > >> > > On Wed, Mar 26, 2014 at 9:56 AM, Sanne Grinovero >> > > <sa...@hibernate.org>wrote: >> > > >> > >> I do of course agree that people should use a single strategy and >> > >> stick to it, so I agree with your reading about what the "general >> > >> expectation" is. >> > >> >> > >> But the original test represents a quite naturally looking example >> > >> and >> > >> it's hard to justify why that should be considered illegal; I'd >> > >> probably be more inclined in making user's life easier than try to >> > >> lecture them about how a proper mapping should look like. >> > >> >> > >> Ignoring any annotation leads to waste of time and debugging >> > >> frustration, so rather than silently discarding a mis-positioned >> > >> annotation I'd prefer a fail-fast approach; that said I think just >> > >> applying them all - as long as there are no obvious conflicting >> > >> annotations - would be even more user friendly and doesn't seem to >> > >> violate any specific wording of the spec. >> > >> >> > >> Sanne >> > >> >> > >> >> > >> On 26 March 2014 13:57, Steve Ebersole <st...@hibernate.org> wrote: >> > >> > Again from the spec (still discussing class-level Access(PROPERTY)) >> > >> > : >> > >> "The >> > >> > behavior is undefined if mapping annotations are placed on any >> > >> > instance >> > >> > variables defined by the class for which Access(FIELD) is not >> > >> specified". >> > >> > >> > >> > Which to me implies that the expectation for switching access for a >> > >> > particular field within such a class is to annotate the *field* >> > >> > with >> > >> > Access(FIELD). >> > >> > >> > >> > Also the footnote to this sections seems very relevant: >> > >> > >> > >> > "[8] ... It is not permitted to specify a field as Access(PROPERTY) >> > >> > or a >> > >> > property as Access(FIELD)..." >> > >> > >> > >> > >> > >> > >> > >> > On Wed, Mar 26, 2014 at 8:02 AM, Emmanuel Bernard < >> > >> emman...@hibernate.org> >> > >> > wrote: >> > >> >> >> > >> >> My reading at the time and what I did find more intuitive is what >> > >> >> the >> > >> >> test represents. >> > >> >> >> > >> >> Entity level @AccessType expresses where the annotations should >> > >> >> be. Otherwise the position of @Id is used to find the access type >> > >> >> to >> > >> >> consider annotation wise. >> > >> >> >> > >> >> If for a few attributes I wish to use the alternative property >> > >> >> access, >> > >> I >> > >> >> can add @AccessType next to the other annotations but expressing >> > >> >> that >> > >> >> the actual property value access is based on the alternative >> > >> >> access. >> > >> >> That way, all annotations are in the same place. >> > >> >> >> > >> >> On Wed 2014-03-26 11:12, Sanne Grinovero wrote: >> > >> >> > As a user I would not expect the @Access annotation to be >> > >> >> > treated as >> > >> a >> > >> >> > special case by the framework in terms of when an annotation is >> > >> >> > ignored, as for example that I can put this on either properties >> > >> >> > or >> > >> >> > fields, and it would not be ignored, while other annotations >> > >> >> > could be >> > >> >> > ignored depending on the position. >> > >> >> > >> > >> >> > Also I highly doubt that there is a practical use case to >> > >> >> > "comment" a >> > >> >> > mapping annotation by moving it to the wrong position (say I >> > >> >> > move a >> > >> >> > @GeneratedValue from a field to a property when using FIELD >> > >> >> > access): >> > >> >> > that would be extremely confusing to maintain. >> > >> >> > >> > >> >> > The spec's wording states "When Access(PROPERTY) is applied to >> > >> >> > an >> > >> >> > [...] mapping annotations **may** be placed on .." >> > >> >> > I'd stress that it doesn' t say "must" but "may", and also >> > >> >> > doesn't >> > >> >> > seem to strictly ban the opposite. >> > >> >> > >> > >> >> > As a user if I put a mapping annotation anywhere I expect it to >> > >> >> > be >> > >> >> > respected, so I would expect the framework to work on the union >> > >> >> > of >> > >> the >> > >> >> > possible positions, and probably even to throw an exception on >> > >> >> > conflicting options. The @Access property would then only be >> > >> >> > used to >> > >> >> > state which access strategy should be used (and a nice effect is >> > >> >> > tha >> > >> >> > the name becomes particularly self-explanatory too). >> > >> >> > >> > >> >> > Also there are many types of possible contradictions in the >> > >> >> > mapping >> > >> >> > options: >> > >> >> > >> > >> >> > public class Course { >> > >> >> > @Id @GeneratedValue(strategy=TABLE) >> > >> >> > private long id; >> > >> >> > ... >> > >> >> > >> > >> >> > @Id @GeneratedValue(strategy=SEQUENCE) >> > >> >> > public long getId() { >> > >> >> > return id; >> > >> >> > } >> > >> >> > >> > >> >> > Or you could have a stronger conflict which isn't solvable via >> > >> >> > AccesType "rules" either: >> > >> >> > >> > >> >> > public class Course { >> > >> >> > @Id @GeneratedValue(strategy=TABLE) >> > >> >> > @Access(AccessType.FIELD) >> > >> >> > private long id; >> > >> >> > ... >> > >> >> > >> > >> >> > @Id @GeneratedValue(strategy=SEQUENCE) >> > >> >> > @Access(AccessType.PROPERTY) >> > >> >> > public long getId() { >> > >> >> > return id; >> > >> >> > } >> > >> >> > >> > >> >> > This last example is the reason why I think you should always >> > >> >> > consistently look at both to collect mapping options, and >> > >> >> > possibly >> > >> >> > throw runtime exceptions. >> > >> >> > >> > >> >> > Sanne >> > >> >> > >> > >> >> > >> > >> >> > >> > >> >> > >> > >> >> > On 26 March 2014 04:13, Steve Ebersole <st...@hibernate.org> >> > >> >> > wrote: >> > >> >> > > >From the test >> > >> >> > > >> > >> >> > > >> > >> >> > >> org.hibernate.test.annotations.access.jpa.AccessMappingTest#testExplicitPropertyAccessAnnotationsWithHibernateStyleOverride >> > >> >> > > we have the following: >> > >> >> > > >> > >> >> > > >> > >> >> > > @Entity >> > >> >> > > @Access(AccessType.PROPERTY) >> > >> >> > > public class Course3 { >> > >> >> > > private long id; >> > >> >> > > ... >> > >> >> > > >> > >> >> > > @Id >> > >> >> > > @GeneratedValue >> > >> >> > > @Access(AccessType.FIELD) >> > >> >> > > public long getId() { >> > >> >> > > return id; >> > >> >> > > } >> > >> >> > > ... >> > >> >> > > } >> > >> >> > > >> > >> >> > > The test asserts that this is a valid mapping. Granted that >> > >> >> > > the >> > >> spec >> > >> >> > > is >> > >> >> > > very unclear here, so I might be missing something. The >> > >> >> > > pertinent >> > >> >> > > spec >> > >> >> > > section here states: >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > >> > >> >> > > *<quote>When Access(PROPERTY) is applied to an entity class, >> > >> >> > > mapped >> > >> >> > > superclass, or embeddableclass, mapping annotations may be >> > >> >> > > placed >> > >> on >> > >> >> > > the >> > >> >> > > properties of that class, and the persistenceprovider runtime >> > >> accesses >> > >> >> > > persistent state via the properties defined by that class. All >> > >> >> > > proper-ties >> > >> >> > > that are not annotated with the Transient annotation are >> > >> persistent. >> > >> >> > > WhenAccess(PROPERTY) is applied to such a class, it is >> > >> >> > > possible to >> > >> >> > > selectively designate indi-vidual attributes within the class >> > >> >> > > for >> > >> >> > > instance >> > >> >> > > variable access. To specify a persistent instancevariable for >> > >> access >> > >> >> > > by the >> > >> >> > > persistence provider runtime, that instance variable must be >> > >> >> > > desig-nated >> > >> >> > > Access(FIELD).</quote>* >> > >> >> > > >> > >> >> > > >> > >> >> > > I can see a few different ways to read that: >> > >> >> > > >> > >> >> > > 1) @Access can be placed on the attribute to define both where >> > >> >> > > to >> > >> look >> > >> >> > > for >> > >> >> > > mapping annotations and the runtime access strategy for a >> > >> >> > > given >> > >> >> > > attribute. >> > >> >> > > Here, we'd do: >> > >> >> > > >> > >> >> > > @Entity >> > >> >> > > @Access(AccessType.PROPERTY) >> > >> >> > > public class Course3 { >> > >> >> > > @Id >> > >> >> > > @GeneratedValue >> > >> >> > > @Access(AccessType.FIELD) >> > >> >> > > private long id; >> > >> >> > > ... >> > >> >> > > >> > >> >> > > public long getId() { >> > >> >> > > return id; >> > >> >> > > } >> > >> >> > > ... >> > >> >> > > } >> > >> >> > > >> > >> >> > > 2) @Access can be placed on the attribute to define the >> > >> >> > > runtime >> > >> access >> > >> >> > > strategy for a given attribute, but the class/hierarchy >> > >> >> > > AccessType >> > >> >> > > controls >> > >> >> > > where to look for mapping annotations. This would lead to: >> > >> >> > > >> > >> >> > > @Entity >> > >> >> > > @Access(AccessType.PROPERTY) >> > >> >> > > public class Course3 { >> > >> >> > > @Access(AccessType.FIELD) >> > >> >> > > private long id; >> > >> >> > > ... >> > >> >> > > >> > >> >> > > @Id >> > >> >> > > @GeneratedValue >> > >> >> > > public long getId() { >> > >> >> > > return id; >> > >> >> > > } >> > >> >> > > ... >> > >> >> > > } >> > >> >> > > >> > >> >> > > The test seems to illustrate that our legacy code made yet a >> > >> >> > > 3rd >> > >> >> > > reading of >> > >> >> > > this passage such that @Access is still considered a "mapping >> > >> >> > > annotation" >> > >> >> > > even though that seems to directly contradict "To specify a >> > >> persistent >> > >> >> > > instance >> > >> >> > > variable for access by the persistence provider runtime, that >> > >> instance >> > >> >> > > variable must be desig- >> > >> >> > > nated Access(FIELD)." >> > >> >> > > >> > >> >> > > >> > >> >> > > Is there some other passage I am missing that bears on what to >> > >> >> > > do >> > >> >> > > here? >> > >> >> > > How do y'all feel about that passage and its implications on >> > >> >> > > this >> > >> >> > > test >> > >> >> > > mapping? >> > >> >> > > _______________________________________________ >> > >> >> > > 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