[hibernate-dev] Another @Access quandry
Sanne Grinovero
sanne at hibernate.org
Wed Mar 26 10:56:44 EDT 2014
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 <steve at 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 <emmanuel at 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 <steve at 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 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