Java Hibernate Annotations - 哪个更好,字段或属性访问?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/594597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate Annotations - Which is better, field or property access?
提问by Martin OConnor
This question is somewhat related to Hibernate Annotation Placement Question.
这个问题与Hibernate Annotation Placement Question有点相关。
But I want to know which is better? Access via properties or access via fields? What are the advantages and disadvantages of each?
但我想知道哪个更好?通过属性访问还是通过字段访问?各自的优缺点是什么?
采纳答案by Miguel Ping
I prefer accessors, since I can add some business logic to my accessors whenever I need. Here's an example:
我更喜欢访问器,因为我可以在需要时向访问器添加一些业务逻辑。下面是一个例子:
@Entity
public class Person {
@Column("nickName")
public String getNickName(){
if(this.name != null) return generateFunnyNick(this.name);
else return "John Doe";
}
}
Besides, if you throw another libs into the mix (like some JSON-converting lib or BeanMapper or Dozer or other bean mapping/cloning lib based on getter/setter properties) you'll have the guarantee that the lib is in sync with the persistence manager (both use the getter/setter).
此外,如果您将另一个库放入混合中(例如一些 JSON 转换库或 BeanMapper 或 Dozer 或其他基于 getter/setter 属性的 bean 映射/克隆库),您将保证该库与持久性同步manager(都使用 getter/setter)。
回答by duffymo
I prefer field access, because that way I'm not forced to provide getter/setter for each property.
我更喜欢字段访问,因为这样我就不会被迫为每个属性提供 getter/setter。
A quick survey via Google suggests that field access is the majority (e.g., http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype).
通过 Google 进行的快速调查表明,现场访问占大多数(例如,http: //java.dzone.com/tips/12-feb-jpa-20-why-accesstype)。
I believe field access is the idiom recommended by Spring, but I can't find a reference to back that up.
我相信字段访问是 Spring 推荐的习惯用法,但我找不到支持它的参考。
There's a related SO questionthat tried to measure performance and came to the conclusion that there's "no difference".
有一个相关的 SO 问题试图衡量性能并得出“没有区别”的结论。
回答by toolkit
I believe property access vs. field access is subtly different with regards to lazy initialisation.
我相信属性访问与字段访问在延迟初始化方面有着微妙的不同。
Consider the following mappings for 2 basic beans:
考虑以下 2 个基本 bean 的映射:
<hibernate-mapping package="org.nkl.model" default-access="field">
<class name="FieldBean" table="FIELD_BEAN">
<id name="id">
<generator class="sequence" />
</id>
<property name="message" />
</class>
</hibernate-mapping>
<hibernate-mapping package="org.nkl.model" default-access="property">
<class name="PropBean" table="PROP_BEAN">
<id name="id">
<generator class="sequence" />
</id>
<property name="message" />
</class>
</hibernate-mapping>
And the following unit tests:
以及以下单元测试:
@Test
public void testFieldBean() {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
FieldBean fb = new FieldBean("field");
Long id = (Long) session.save(fb);
tx.commit();
session.close();
session = sessionFactory.openSession();
tx = session.beginTransaction();
fb = (FieldBean) session.load(FieldBean.class, id);
System.out.println(fb.getId());
tx.commit();
session.close();
}
@Test
public void testPropBean() {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
PropBean pb = new PropBean("prop");
Long id = (Long) session.save(pb);
tx.commit();
session.close();
session = sessionFactory.openSession();
tx = session.beginTransaction();
pb = (PropBean) session.load(PropBean.class, id);
System.out.println(pb.getId());
tx.commit();
session.close();
}
You will see the subtle difference in the selects required:
您将看到所需选择的细微差别:
Hibernate:
call next value for hibernate_sequence
Hibernate:
insert
into
FIELD_BEAN
(message, id)
values
(?, ?)
Hibernate:
select
fieldbean0_.id as id1_0_,
fieldbean0_.message as message1_0_
from
FIELD_BEAN fieldbean0_
where
fieldbean0_.id=?
0
Hibernate:
call next value for hibernate_sequence
Hibernate:
insert
into
PROP_BEAN
(message, id)
values
(?, ?)
1
That is, calling fb.getId()
requires a select, whereas pb.getId()
does not.
也就是说,调用fb.getId()
需要选择,而不需要pb.getId()
。
回答by 01es
That really depends on a specific case -- both options are available for a reason. IMO it boils down to three cases:
这实际上取决于特定情况——这两种选择都是有原因的。IMO 归结为三种情况:
- setter has some logic that should not be executed at the time of loading an instance from a database; for example, some value validation happens in the setter, however the data coming from db should be valid (otherwise it would not get there (: ); in this case field access is most appropriate;
- setter has some logic that should always be invoked, even during loading of an instance from db; for example, the property being initialised is used in computation of some calculated field (e.g. property -- a monetary amount, calculated property -- a total of several monetary properties of the same instance); in this case property access is required.
- None of the above cases -- then both options are applicable, just stay consistent (e.i. if field access is the choice in this situation then use it all the time in similar situation).
- setter 有一些不应该在从数据库加载实例时执行的逻辑;例如,setter 中发生了一些值验证,但是来自 db 的数据应该是有效的(否则它不会到达那里 (:);在这种情况下,字段访问是最合适的;
- setter 有一些应该始终被调用的逻辑,即使在从 db 加载实例期间也是如此;例如,正在初始化的属性用于计算某些计算字段(例如,属性——货币金额,计算属性——同一实例的几个货币属性的总数);在这种情况下,需要访问属性。
- 以上情况都不是——那么这两个选项都适用,只要保持一致(即如果在这种情况下选择字段访问,那么在类似情况下一直使用它)。
回答by Vladimir Dyuzhev
Normally beans are POJO, so they have accessors anyway.
通常 bean 是 POJO,因此它们无论如何都有访问器。
So the question is not "which one is better?", but simply "when to use field access?". And the answer is "when you don't need a setter/getter for the field!".
所以问题不是“哪个更好?”,而只是“何时使用现场访问?”。答案是“当您不需要该领域的 setter/getter 时!”。
回答by Justin Standard
I think annotating the property is better because updating fields directly breaks encapsulation, even when your ORM does it.
我认为注释属性更好,因为更新字段会直接破坏封装,即使您的 ORM 这样做也是如此。
Here's a great example of where it will burn you: you probably want your annotations for hibernate validator & persistence in the same place (either fields or properties). If you want to test your hibernate validator powered validations which are annotated on a field, you can't use a mock of your entity to isolate your unit test to just the validator. Ouch.
这是一个很好的例子,它会烧掉你:你可能希望你的 hibernate 验证器和持久性的注释在同一个地方(字段或属性)。如果要测试在字段上注释的休眠验证器支持的验证,则不能使用实体的模拟将单元测试隔离到验证器。哎哟。
回答by Justin Standard
i thinking about this and i choose method accesor
我在考虑这个,我选择了方法访问器
why?
为什么?
because field and methos accesor is the same but if later i need some logic in load field, i save move all annotation placed in fields
因为 field 和methos accesor 是相同的,但是如果稍后我需要在加载字段中使用一些逻辑,我会保存移动放置在字段中的所有注释
regards
问候
Grubhart
格鲁哈特
回答by sundary
I had the same question regarding accesstype in hibernate and found some answers here.
回答by Pascal Thivent
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-3718get resolved).
- 如果需要,我可以添加逻辑(如已接受的答案中所述)。
- 它允许我在
foo.getId()
不初始化代理的情况下调用(使用 Hibernate 时很重要,直到HHH-3718得到解决)。
Drawback:
退税:
- it makes the code less readable, you have for example to browse a whole class to see if there are
@Transient
around there.
- 它使代码的可读性降低,例如,您必须浏览整个类以查看那里是否
@Transient
有。
回答by HDave
Here's a situation where you HAVE to use property accessors. Imagine you have a GENERIC abstract class with lots of implementation goodness to inherit into 8 concrete subclasses:
在这种情况下,您必须使用属性访问器。想象一下,你有一个 GENERIC 抽象类,它有很多实现优点,可以继承到 8 个具体的子类中:
public abstract class Foo<T extends Bar> {
T oneThing;
T anotherThing;
// getters and setters ommited for brevity
// Lots and lots of implementation regarding oneThing and anotherThing here
}
Now exactly how should you annotate this class? The answer is YOU CAN'T annotate it at all with either field or property access because you can't specify the target entity at this point. You HAVE to annotate the concrete implementations. But since the persisted properties are declared in this superclass, you MUST used property access in the subclasses.
现在到底应该如何注释这个类?答案是您根本无法使用字段或属性访问对其进行注释,因为此时您无法指定目标实体。您必须注释具体的实现。但是由于持久化的属性是在这个超类中声明的,你必须在子类中使用属性访问。
Field access is not an option in an application with abstract generic super-classes.
在具有抽象通用超类的应用程序中,字段访问不是一个选项。