在上一篇文章中,我展示了一种持久保存实体的简单方法。 我解释了JPA用于确定实体默认表的默认方法。 假设我们要覆盖此默认名称。 我们之所以喜欢这样做,是因为数据模型是以前设计和修复的,并且表名与我们的类名不匹配(例如,我见过人们创建带有“ tbl_”前缀的表)。 那么我们应该如何覆盖默认表名称以匹配现有数据模型?

事实证明,这非常简单。 如果我们需要覆盖JPA假定的默认表名,则有两种方法可以做到:

  1. 我们可以使用@Entity批注的name属性来提供一个明确的实体名称,以与数据库表名称匹配。 对于我们的示例,如果表名是tbl_address,则可以在Address类中使用@Entity(name =“ tbl_address”)
  2. 我们可以在@Entity批注下面使用@Table (在javax.persistence包中定义)注解,并使用其name属性显式指定表名。
@Entity
@Table(name = "tbl_address")
public class Address {// Rest of the class
}

通过这两种方法,@ Table批注提供了更多用于自定义映射的选项。 例如,某些数据库(例如PostgreSQL)具有schema的概念,您可以使用schema进一步对表进行分类/分组。 由于此功能,您可以在一个数据库中创建两个具有相同名称的表(尽管它们将属于两个不同的模式)。 要访问这些表,然后在查询中添加架构名称作为表前缀。 因此,如果PostgreSQL数据库有两个不同的模式,分别命名为public (这类似于PostgreSQL数据库的默认模式)和document ,并且这两个模式都包含名为document_collection的表,那么这两个查询都是完全有效的:

-- fetch from the table under public schema
SELECT *
FROM   public.document_collection;-- fetch from the table under document schema
SELECT *
FROM   document.document_collection;

为了将实体映射到文档架构中的document_collection表,您将使用@Table注释,其架构属性设置为document

@Entity
@Table(name="document_collection", schema="document")
public class DocumentCollection {// rest of the class
}

当以这种方式指定时,就像我们在查询中所做的那样,当JPA进入数据库以访问表时,架构名称将作为表名称的前缀添加。

如果不是在@ Table批注中指定架构名称,而是在表名称本身中附加了架构名称,该怎么办呢?

@Entity
@Table(name = "document.document_collection")
public class DocumentCollection {// rest of the class
}

不能保证以这种方式将模式名称与表名称内联,因为在JPA规范(非标准)中未指定对此名称的支持。 因此,即使您的持久性提供程序支持它,也最好不要养成这样做的习惯。

接下来,我们将注意力转移到各列。 为了确定默认列,JPA进行了类似于以下操作:

  1. 首先,它检查是否给出了任何显式的列映射信息。 如果找不到列映射信息,它将尝试猜测列的默认值。
  2. 为了确定默认值,JPA需要知道实体状态的访问类型,即读取/写入实体状态的方式。 在JPA中,两种不同的访问类型是可能的-字段和属性。 在我们的示例中,我们使用了字段访问(实际上,JPA从@Id批注的位置/位置假定了这一点,但稍后会对此进行更多介绍)。 如果您使用此访问类型,则将使用Reflection API从实体字段直接写入/读取状态。
  3. 知道访问类型后,JPA然后尝试确定列名称。 对于字段访问类型,JPA直接将字段名称视为列名称,这意味着如果实体具有名为status的字段,则它将映射到名为status的列。

至此,我们应该很清楚地址实体的状态是如何保存到相应列中的。 Address实体的每个字段在数据库表tbl_address中都有一个对应的列,因此JPA将它们直接保存到其对应的列中。 id字段已保存到id列中, city字段已保存到city列中,依此类推。

好的,接下来让我们继续覆盖列名。 据我所知,只有一种方法(如果您碰巧知道任何其他方法,请注释!)来覆盖实体状态的默认列名,这是通过使用@Column (在javax.persistence包中定义的) )注释。 因此,如果将tbl_address表的id列重命名为address_id,则可以将字段名称更改为address_id ,也可以使用@Column批注将其name属性设置为address_id

@Entity
@Table(name = "tbl_address")
public class Address {@Id@GeneratedValue@Column(name = "address_id")private Integer id;// Rest of the class
}

您可以看到,对于上述所有情况,JPA使用的默认方法都非常明智,大多数情况下您都会对此感到满意。 但是,更改默认值也很容易,并且可以很快完成。

如果我们在地址实体中有一个不希望保存在数据库中的字段怎么办? 假设Address实体有一个名为transientColumn的列,该列在数据库表中没有任何对应的默认列:

@Entity
@Table(name = "tbl_address")
public class Address {@Id@GeneratedValue@Column(name = "address_id")private Integer id;private String street;private String city;private String province;private String country;private String postcode;private String transientColumn;// Rest of the class
}

如果使用上述更改来编译代码,则将出现如下所示的异常:

Exception in thread “main” java.lang.ExceptionInInitializerError
at com.keertimaan.javasamples.jpaexample.Main.main(Main.java:33)
Caused by: javax.persistence.PersistenceException: Unable to build entity manager factory
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:83)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at com.keertimaan.javasamples.jpaexample.persistenceutil.PersistenceManager.<init>(PersistenceManager.java:31)
at com.keertimaan.javasamples.jpaexample.persistenceutil.PersistenceManager.<clinit>(PersistenceManager.java:26)
… 1 more
Caused by: org.hibernate.HibernateException: Missing column: transientColumn in jpa_example.tbl_address
at org.hibernate.mapping.Table.validateColumns(Table.java:365)
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1336)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:155)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:525)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
… 6 more

例外情况是,持久性提供程序无法在数据库中找到任何名称为transientColumn的列 ,并且我们没有采取任何措施使持久性提供程序明确表示我们不希望将此字段保存在数据库中。 持久性提供程序将其用作实体中映射到数据库列的任何其他字段。

为了解决此问题,我们可以执行以下任一操作:

  1. 我们可以使用@Transient (在javax.persistence包中定义)注解来对transientColumn字段进行注解,以使持久性提供程序知道我们不希望保存该字段,并且该表中没有任何对应的列。
  2. 我们可以使用Java默认具有的transient关键字。

我想到的这两种方法之间的区别在于,如果我们使用transient关键字而不是annotation,则如果Address对象之一从一个JVM序列化到另一个JVM,那么transitionColumn字段将再次被重新初始化(就像Java中的其他任何临时字段)。 对于注释,这不会发生,并且transientColumn字段将在序列化过程中保留其值。 根据经验,如果我不需要担心序列化(在大多数情况下不需要),我总是使用批注。

因此,使用注释,我们可以立即解决问题:

@Entity
@Table(name = "tbl_address")
public class Address {@Id@GeneratedValue@Column(name = "address_id")private Integer id;private String street;private String city;private String province;private String country;private String postcode;@Transientprivate String transientColumn;// Rest of the class
}

今天的人们就这样。 如果发现任何错误/有任何意见,请随时发表评论!

直到下一次。

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

JPA教程:实体映射-第2部分相关推荐

  1. JPA教程:映射实体–第1部分

    在本文中,我将讨论JPA中的实体映射过程. 至于我的示例,我将使用与 我以前的一篇文章中使用的模式相同的模式 . 在前两篇文章中,我解释了如何在Java SE环境中设置JPA. 我不打算为Web应用程 ...

  2. Spring Boot 入门系列(二十八) JPA 的实体映射关系,一对一,一对多,多对多关系映射!...

    前面讲了Spring Boot 使用 JPA,实现JPA 的增.删.改.查的功能,同时也介绍了JPA的一些查询,自定义SQL查询等使用.JPA使用非常简单,功能非常强大的ORM框架,无需任何数据访问层 ...

  3. jpa 实体映射视图_JPA教程:映射实体–第1部分

    jpa 实体映射视图 在本文中,我将讨论JPA中的实体映射过程. 至于我的示例,我将使用与 我以前的一篇文章中使用的模式相同的模式 . 在前两篇文章中,我解释了如何在Java SE环境中设置JPA. ...

  4. JPA教程:JPA概述、JPA实体生命周期、JPA实体映射关系、JPA查询语言

    JPA定义了Java ORM及实体操作API的标准.本文摘录了JPA的一些关键信息以备查阅. 如果有hibernate的基础,通过本文也可以快速掌握JPA的基本概念及使用. 1 JPA概述 JPA(J ...

  5. jpa 实体映射视图_JPA教程:实体映射-第2部分

    jpa 实体映射视图 在上一篇文章中,我展示了一种持久保存实体的简单方法. 我解释了JPA用于确定实体默认表的默认方法. 假设我们要覆盖此默认名称. 我们之所以喜欢这样做,是因为数据模型是以前设计和修 ...

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

    jpa 实体映射视图 在上一篇文章中,我展示了两种读取/写入持久实体状态的不同方法-字段和属性. 使用字段访问模式时,JPA使用反射直接从实体的字段读取状态值. 如果我们没有明确指定列名,它将直接将字 ...

  7. Spring Data JPA教程

    在Java类或对象与关系数据库之间管理数据是一项非常繁琐且棘手的任务. DAO层通常包含许多样板代码,应简化这些样板代码,以减少代码行数并使代码可重复使用. 在本教程中,我们将讨论Spring数据的J ...

  8. Spring Data JPA教程:简介

    创建使用Java Persistence API的存储库是一个繁琐的过程,需要大量时间,并且需要大量样板代码. 通过执行以下步骤,我们可以消除一些样板代码: 创建一个抽象的基础存储库类,该类为实体提供 ...

  9. Spring Data JPA教程第一部分:配置

    Spring Data JPA是一个旨在简化基于JPA的存储库的创建并减少与数据库通信所需的代码量的项目. 在我的工作和个人爱好项目中,我已经使用了一段时间,确实使事情变得更加简单和整洁. 现在是时候 ...

最新文章

  1. 1057 Stack
  2. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 远程 目标进程 中的 /system/lib/libc.so 动态库中的 mmap 函数地址 )
  3. 将redis作为windows服务安装
  4. 免费下载来自阿里巴巴 双11 的《云原生大规模应用落地指南》
  5. 自适应宽_移动端实现自适应缩放界面的方法汇总
  6. 致敬F1七冠王!Redmi K50电竞版邀请函曝光 打造掌上梦幻跑车
  7. android app 控制背光,android7.1+msm8937背光控制
  8. 极米h3s和坚果j10、当贝f3三款投影实测对比来了!
  9. Java篇第三回——运算符、表达式与语句(C不好的也快来)
  10. [译]Flutter缓存管理库flutter_cache_manager
  11. 整合stripe线上支付收款
  12. 我的世界mod整合包java_我的世界1.10.2mod大全+整合包+合集
  13. 利用sfntly的sfnttool.jar提取中文字体
  14. 西安计算机三本院校排名2015,2015年陕西三本院校排名
  15. 50个酷到受不了的RIA应用
  16. python 凯撒密码加密和暴力破解
  17. 计算机专业srtp项目选题,我都大二了,才知道什么是SRTP
  18. Shell- ipv6地址的格式转化
  19. [幻灯片]软件需求设计方法学全程实例剖析-01-概述
  20. xposed输出qq加密前明文数据

热门文章

  1. SpringCloud(笔记)
  2. Linux中打包和解压到的方法
  3. amazon php 空间,(四)Amazon Lightsail 部署LAMP应用程序之扩展PHP前端
  4. php mysql 编码为utf-8_php连mysql用 utf-8编码乱码怎么办
  5. org.springframework.uti包下的StringUtils的使用和org.apache.commons.lang包下StringUtils的使用
  6. 机器人点焊枪接线_用于焊接机器人焊枪工具点及工件坐标系标定装置及方法与流程...
  7. python表单提交的两种方式_Flask框架学习笔记之表单基础介绍与表单提交方式
  8. 多个定时器相互干扰的问题_相互问题
  9. lock.lock_HibernateCascadeType.LOCK陷阱
  10. gradle构建多模块项目_Gradle入门:创建多项目构建