Hibernate Annotations - Which is better, field or property access?

后端 未结 25 1215
说谎
说谎 2020-11-22 15:02

This question is somewhat related to Hibernate Annotation Placement Question.

But I want to know which is better? Access via properties or access vi

相关标签:
25条回答
  • 2020-11-22 15:33

    There are arguments for both, but most of them stem from certain user requirements "what if you need to add logic for", or "xxxx breaks encapsulation". However, nobody has really commented on the theory, and given a properly reasoned argument.

    What is Hibernate/JPA actually doing when it persists an object - well, it is persisting the STATE of the object. That means storing it in a way that it can be easily reproduced.

    What is encapsulation? Encapsulations means encapsulating the data (or state) with an interface that the application/client can use to access the data safely - keeping it consistent and valid.

    Think of this like MS Word. MS Word maintains a model of the document in memory - the documents STATE. It presents an interface that the user can use to modify the document - a set of buttons, tools, keyboard commands etc. However, when you choose to persist (Save) that document, it saves the internal state, not the set of keypresses and mouse clicks used to generate it.

    Saving the internal state of the object DOES NOT break encapsulation - otherwise you don't really understand what encapsulation means, and why it exists. It is just like object serialisation really.

    For this reason, IN MOST CASES, it is appropriate to persist the FIELDS and not the ACCESSORS. This means that an object can be accurately recreated from the database exactly the way it was stored. It should not need any validation, because this was done on the original when it was created, and before it was stored in the database (unless, God forbid, you are storing invalid data in the DB!!!!). Likewise, there should be no need to calculate values, as they were already calculated before the object was stored. The object should look just the way it did before it was saved. In fact, by adding additional stuff into the getters/setters you are actually increasing the risk that you will recreate something that is not an exact copy of the original.

    Of course, this functionality was added for a reason. There may be some valid use cases for persisting the accessors, however, they will typically be rare. An example may be that you want to avoid persisting a calculated value, though you may want to ask the question why you don't calculate it on demand in the value's getter, or lazily initialise it in the getter. Personally I cannot think of any good use case, and none of the answers here really give a "Software Engineering" answer.

    0 讨论(0)
  • 2020-11-22 15:33

    I had the same question regarding accesstype in hibernate and found some answers here.

    0 讨论(0)
  • 2020-11-22 15:35

    I tend to prefer and to use property accessors:

    • I can add logic if the need arises (as mentioned in the accepted answer).
    • it allows me to call foo.getId() without initializing a proxy (important when using Hibernate, until HHH-3718 get resolved).

    Drawback:

    • it makes the code less readable, you have for example to browse a whole class to see if there are @Transient around there.
    0 讨论(0)
  • 2020-11-22 15:35

    Both :

    The EJB3 spec requires that you declare annotations on the element type that will be accessed, i.e. the getter method if you use property access, the field if you use field access.

    https://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping

    0 讨论(0)
  • 2020-11-22 15:36

    Are we there yet

    That's an old presentation but Rod suggests that annotation on property access encourages anemic domain models and should not be the "default" way to annotate.

    0 讨论(0)
  • 2020-11-22 15:37

    Let me try to summarize the most important reasons for choosing field-based access. If you want to dive deeper, please read this article on my blog: Access Strategies in JPA and Hibernate – Which is better, field or property access?

    Field-based access is by far the better option. Here are 5 reasons for it:

    Reason 1: Better readability of your code

    If you use field-based access, you annotate your entity attributes with your mapping annotations. By placing the definition of all entity attributes at the top of your class, you get a relatively compact view of all attributes and their mappings.

    Reason 2: Omit getter or setter methods that shouldn’t be called by your application

    Another advantage of field-based access is that your persistence provider, e.g., Hibernate or EclipseLink, doesn’t use the getter and setter methods of your entity attributes. That means that you don’t need to provide any method that shouldn’t be used by your business code. This is most often the case for setter methods of generated primary key attributes or version columns. Your persistence provider manages the values of these attributes, and you should not set them programmatically.

    Reason 3: Flexible implementation of getter and setter methods

    Because your persistence provider doesn’t call the getter and setter methods, they are not forced to fulfill any external requirements. You can implement these methods in any way you want. That enables you to implement business-specific validation rules, to trigger additional business logic or to convert the entity attribute into a different data type.

    You can, for example, use that to wrap an optional association or attribute into a Java Optional.

    Reason 4: No need to mark utility methods as @Transient

    Another benefit of the field-based access strategy is that you don’t need to annotate your utility methods with @Transient. This annotation tells your persistence provider that a method or attribute is not part of the entity persistent state. And because with field-type access the persistent state gets defined by the attributes of your entity, your JPA implementation ignores all methods of your entity.

    Reason 5: Avoid bugs when working with proxies

    Hibernate uses proxies for lazily fetched to-one associations so that it can control the initialization of these associations. That approach works fine in almost all situations. But it introduces a dangerous pitfall if you use property-based access.

    If you use property-based access, Hibernate initializes the attributes of the proxy object when you call the getter method. That’s always the case if you use the proxy object in your business code. But quite a lot of equals and hashCode implementations access the attributes directly. If this is the first time you access any of the proxy attributes, these attributes are still uninitialized.

    0 讨论(0)
提交回复
热议问题