在使用JPA映射类时,为什么有人会在getter或setter上添加注释?

时间:2010-11-15 19:28:45

标签: java hibernate jpa annotations mapping

主题说明了一切......到目前为止,我认为人们在吸气剂和/或制定者上宣布注释没有任何好处。对我来说,这只有在课堂上传播注释的缺点,这会使课程更难以理解。

在字段上添加注释会明显减少需要帮助时要发布的代码量。这只是一个很小的优势。但是对方法进行注释对我没有任何意义。

4 个答案:

答案 0 :(得分:42)

在方法上添加注释会强制JPA通过方法访问属性。当对象的内部状态与数据库模式不同时,这是有意义的:

@Entity
public class Employee {
    private String firstName;
    private String lastName;

    @Column(name = "EMP_NAME") // Due to legacy database schema
    public String getName() {
        return fisrtName + " " + lastName;
    }

    public void setName(String name) {
        ...
    }

    ... Getters and setters for firstName and lastName with @Transient ...
}

在JPA 2.0中,您可以使用@Access

指定细粒度级别的访问类型
@Entity @Access(AccessType.FIELD)
public class Employee {
    @Access(AccessType.PROPERTY) @Column(name = "EMP_NAME")
    public String getName() { ... }
    ... other properties have field access ...
}

答案 1 :(得分:22)

  

在使用JPA映射类时,为什么有人会在getter或setter上添加注释?

如前所述,如果需要,使用属性访问允许在getter中添加逻辑。

但由于问题标记为,我会提到另一个(巨大的)好处:属性访问权限允许您拨打foo.getId() 初始化代理 。使用字段访问时,您无法获得相同的行为。 Emmanuel Bernard解释了现场访问的这种限制如下:

  

这是不幸的,但是预料到的。这是字段级访问的限制之一。   基本上我们无法知道getId()确实只能访问id字段。所以我们需要加载整个对象才能安全。

所以是的,使用属性访问会使代码更难阅读,例如,您可以浏览整个类以查看周围是否有@Transient。但对我来说,这个好处(至少)远远超过了这个劣势。

相关问题

参考

答案 2 :(得分:2)

给出的答案是正确的。注释方法而不是属性为您提供:

  1. 使用getId()的权利,如果它被标记为@Id值,则从代理对象获取外键值而不实际从数据库加载它。

    < / LI>
  2. 您可以创建更新不在数据库中的内部对象状态的getter / setter。我从DB中检索压缩状态时使用了这个,我希望在对象内解压缩成更有用的内部成员数据。设置器和getter设置并获得压缩状态,DB和Hibernate不会知道&#34;关于未压缩的内部成员。

  3. 我有一个缺点:

    一个。你的二传手必须非常简单。 Hibernate希望他们能够通过直接分配给成员数据来完成所需的工作。 A&#34; setCategory&#34;方法不仅可以设置类别,还可以更新相关的Category对象来显示关系,可能会让您陷入麻烦。

答案 3 :(得分:0)

我在getter / setter上使用注释,因为我有一个与实现分离的API,我想保持API部分完全没有框架,允许我切换框架或提供不同的实现。例如,现在我使用的是spring-data-jpa,但是使用下面的API,我可以轻松切换到spring-jdbc或任何其他框架。

我所做的是为控制器,存储库和实体定义接口,如下所示:

public interface MyEntityController<T extends MyEntity> {
    Iterable<T> listEntities();
    T getEntity(Long id);
}

public interface MyEntityService<T extends MyEntity> {
    Iterable<T> findAll();
    T findById(Long id);
}

public interface MyEntityRepository<T extends MyEntity> {
    Iterable<T> findAll();
    T findOne(Long id);
}

// no JPA annotations here
public abstract class MyEntity {
    protected Long id;
    protected String myField;
}

接下来,我只需按如下方式实现MyEntity,并将MyEntityImpl用于Controller,Service和Repository实现:

@Entity
public class MyEntityImpl extends MyEntity {
    @Id public long getId() { return id; }
    @Column public String getMyField() { return myField };
    // setters, etc
}

@Repository
public interface MyEntityRepositoryImpl extends MyEntityRepository, JPARepository<MyEntityImpl, Long> {
}

我已经测试过了,它运行正常。仅使用MyEntityImpl注释@Entity是行不通的,因为超类需要是@MappedSuperclass