jpa 实体映射视图_JPA教程:实体映射-第3部分

jpa 实体映射视图

上一篇文章中,我展示了两种读取/写入持久实体状态的不同方法-字段和属性。 使用字段访问模式时,JPA使用反射直接从实体的字段读取状态值。 如果我们没有明确指定列名,它将直接将字段名转换为数据库列名。 在属性访问模式下,getter / setter方法用于读取/写入状态值。 在这种情况下,我们使用相同的注释来注释实体状态的getter方法,而不是字段。 如果我们未明确指定数据库列名称,则按照JavaBean约定确定它们,即通过从getter方法名称中删除“ get”部分并将方法名称其余部分的首字母转换为小写字符来确定。


我们可以通过在实体类声明中使用@Access注释来指定用于实体的访问方式。 此注释采用AccessType类型的参数(在javax.persistence包中定义)枚举,该参数具有对应于两种不同访问模式( FIELDPROPERTY )的两个不同值。 例如,我们可以通过以下方式为Address实体指定属性访问模式:

@Entity
@Table(name = "tbl_address")
@Access(AccessType.PROPERTY)
public class Address {
  private Integer id;
  private String street;
  private String city;
  private String province;
  private String country;
  private String postcode;
  private String transientColumn;

  @Id
  @GeneratedValue
  @Column(name = "address_id")
  public Integer getId() {
    return id;
  }

  public Address setId(Integer id) {
    this.id = id;
    return this;
  }

  public String getStreet() {
    return street;
  }

  public Address setStreet(String street) {
    this.street = street;
    return this;
  }

  public String getCity() {
    return city;
  }

  public Address setCity(String city) {
    this.city = city;
    return this;
  }

  public String getProvince() {
    return province;
  }

  public Address setProvince(String province) {
    this.province = province;
    return this;
  }

  public String getCountry() {
    return country;
  }

  public Address setCountry(String country) {
    this.country = country;
    return this;
  }

  public String getPostcode() {
    return postcode;
  }

  public Address setPostcode(String postcode) {
    this.postcode = postcode;
    return this;
  }
}

关于上述示例的几点注意事项:

  1. 如前所述,我们现在使用@ Id, @ GeneratedValue@Column注释注释实体ID的getter方法。
  2. 由于现在列名称将通过解析getter方法来确定,因此我们不再需要使用@Transient注释来标记transientColumn字段。 但是,如果Address实体具有名称以“ get”开头的任何其他方法,则我们需要在其上应用@Transient

如果一个实体没有显式的访问模式信息,就像我们在本系列第一部分中创建的Address实体一样,那么JPA会采用默认的访问模式。 这个假设不是随机的。 相反,JPA首先尝试找出@Id批注的位置。 如果在字段上使用@Id批注,则假定为字段访问模式。 如果在getter方法上使用@Id批注,则假定为属性访问模式。 因此,即使在上例中从地址实体中删除@Access批注,映射仍将有效,并且JPA将采用属性访问模式:

@Entity
@Table(name = "tbl_address")
public class Address {
  private Integer id;
  private String street;
  private String city;
  private String province;
  private String country;
  private String postcode;
  private String transientColumn;

  @Id
  @GeneratedValue
  @Column(name = "address_id")
  public Integer getId() {
    return id;
  }

  // Rest of the class........

有关访问模式,需要记住的一些重要要点:

  1. 如果使用字段访问模式,则永远不要将字段声明为公共字段。 实体的所有字段都应具有专用 (最佳!), 受保护或默认访问类型。 其背后的原因是,将字段声明为public将允许任何不受保护的类直接访问实体状态,这很容易破坏提供程序的实现。 例如,假设您有一个实体,其所有字段都是公共的。 现在,如果此实体是一个受管实体(这意味着它已保存到数据库中),并且任何其他类都更改了其id的值,然后尝试将所做的更改保存回数据库,则可能会遇到不可预知的行为(在以后的文章中将尝试详细阐述该主题)。 甚至实体类本身也只能在初始化期间直接操作字段(即,在构造函数内部)。
  2. 在属性访问模式下,如果我们将注释应用于setter方法而不是getter方法,则将忽略它们。

也可以将这两种访问类型混合使用。 假设您要对实体的除一种状态外的所有状态都使用字段访问模式,对于其余一种状态,您想使用属性访问模式,因为您想在向/从状态值读取/写入状态值之前执行某种转换。数据库。 您可以按照以下步骤轻松完成此操作:

  1. @Access批注标记实体,并指定AccessType.FIELD作为所有字段的访问方式。
  2. 使用@Transient批注标记您不喜欢使用字段访问模式的字段。
  3. @Access批注标记属性的getter方法,并指定AccessType.PROPERTY作为访问方式。

下面的示例演示了这种方法,因为将邮政编码更改为使用属性访问模式:

@Entity
@Table(name = "tbl_address")
@Access(AccessType.FIELD)
public class Address {
  @Id
  @GeneratedValue
  @Column(name = "address_id")
  private Integer id;

  private String street;
  private String city;
  private String province;
  private String country;
 
  /**
    * postcode is now marked as Transient
    */
  @Transient
  private String postcode;
 
  @Transient
  private String transientColumn;

  public Integer getId() {
    return id;
  }

  public Address setId(Integer id) {
    this.id = id;
    return this;
  }

  public String getStreet() {
    return street;
  }

  public Address setStreet(String street) {
    this.street = street;
    return this;
  }

  public String getCity() {
    return city;
  }

  public Address setCity(String city) {
    this.city = city;
    return this;
  }

  public String getProvince() {
    return province;
  }

  public Address setProvince(String province) {
    this.province = province;
    return this;
  }

  public String getCountry() {
    return country;
  }

  public Address setCountry(String country) {
    this.country = country;
    return this;
  }

  /**
    * We are now using property access mode for reading/writing
    * postcode
    */
  @Access(AccessType.PROPERTY)
  public String getPostcode() {
    return postcode;
  }

  public Address setPostcode(String postcode) {
    this.postcode = postcode;
    return this;
  }
}

这里要注意的重要一点是,如果我们不使用@Access注释对类进行注释,以将字段访问模式显式指定为默认模式,而是对字段和getter方法进行注释,则映射的结果行为将是不确定的。 这意味着结果将完全取决于持久性提供程序,即一个提供程序可能选择使用字段访问模式作为默认值,一个提供程序可能使用属性访问模式,或者一个可能决定引发异常!

今天就这样。 如果您发现任何问题/有任何疑问,请随时发表评论!

直到下一次。

翻译自: https://www.javacodegeeks.com/2014/10/jpa-tutorial-mapping-entities-part-3.html

jpa 实体映射视图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值