JPA教程:实体映射-第2部分

在上一篇文章中,我展示了一种持久保存实体的简单方法。 我解释了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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue DOM事件

本文参考自&#xff1a;https://mp.weixin.qq.com/s?src3&timestamp1527154113&ver1&signaturetWGeTa86gyK*RL0P7nwlA6-8V14FjzxUTh7CM9kQLjl0DV3sx*2hKauMGZKoYBkTSp14Zw6MOD8pU-haYmJoNTSBI5rptCZwf3wTIXLUMUOYDOPZtxm9wJaSm0l7vqshH98ToXQCcfm-5jR-Y66eAYzuFM5…

2019.06.17课件:[洛谷P1310]表达式的值 题解

P1310 表达式的值 题目描述 给你一个带括号的布尔表达式&#xff0c;其中表示或操作|&#xff0c;*表示与操作&&#xff0c;先算*再算。但是待操作的数字&#xff08;布尔值&#xff09;不输入。 求能使最终整个式子的值为0的方案数。 题外话 不久之前我在codewars上做过一…

vue+element 封装日期范围组件(双向绑定)

像这样的日期组件&#xff0c;在后台管理项目中是比较多的&#xff0c;而且加了快捷选项&#xff0c;代码量较多&#xff0c;因此封装成组件。 封装这一类型的组组件&#xff0c;主要是了解输入框双向绑定 v-model 的过程。 1、了解输入框双向绑定的过程&#xff1a; 官网&am…

句柄是什么?1

句柄是什么&#xff1f; 1.句柄是什么&#xff1f; 在windows中&#xff0c;句柄是和对象一一对应的32位无符号整数值。对象可以映射到唯一的句柄&#xff0c;句柄也可以映射到唯一的对象。2.为什么我们需要句柄&#xff1f; 更准确地说&#xff0c;是windows需要句柄。w…

用Hystrix保护您的应用程序

在之前的帖子http://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html中&#xff0c;我们讨论了微服务以及如何使用&#xff08;RxJava&#xff09;的Reactive Extensions编排微服务。 但是&#xff0c;如果一项或多项服务由于已被暂停或引发异常而…

python方法未绑定错误

相信 Python 程序员多多少少都和我一样遇到过 Method Unbound Error&#xff0c;直译过来就是 “方法未绑定错误”&#xff0c;虽然搜索之后知道了使用 classmethod 这样的装饰起后就可以解决问题&#xff0c; 但是一直没有得到完全解惑。 我们知道&#xff0c;Python 是一个动…

若依 从下载到成功运行及打包

官网&#xff1a;http://www.ruoyi.vip/ 目录 一、下载并运行项目 二、关于 若依 接口地址配置 2.1 若依的跨域代理介绍 2.2 配置跨域代理&#xff0c;调用后台接口 2.2.1 配置 后台 ip 地址 2.2.2 页面报“系统接口404”错误 三、打包配置 3.1 打包之后静态资源404…

Windows平台下 找回已丢失的MySql root 用户密码

该随笔供初学MySql者作为参考&#xff0c;本人第一次写博客&#xff0c;欢迎各位大虾拍砖&#xff01; 主要步骤&#xff1a; 1.关闭MySql服务 2.在控制台下键入cd命令&#xff0c;进入MySql的安装目录的Bin目录下 3.键入命令 mysqld --skip-grant-tables(参数大致意思&#xf…

JPA教程:实体映射-第3部分

在上一篇文章中&#xff0c;我展示了两种读取/写入持久实体状态的不同方法-字段和属性。 使用字段访问模式时&#xff0c;JPA使用反射直接从实体的字段读取状态值。 如果我们没有明确指定列名&#xff0c;它将直接将字段名转换为数据库列名。 在属性访问模式下&#xff0c;使用…

uniAPP小程序 子组件使用watch不生效,H5正常,小程序不正常(其实是子组件model选项的问题)

第一次用 uniapp 写小程序&#xff0c;还是遇到挺多问题的。写了一个下拉多选组件&#xff0c;发现同样的代码&#xff0c;在H5上运行效果正常&#xff0c;在小程序上压根不走 watch 。 uniapp官网&#xff1a;【全局配置 | uni-app官网】 看文档 watch 是支持H5、小程序的&…

jQuery EasyUI/TopJUI创建日期时间输入框

jQuery EasyUI/TopJUI创建日期时间输入框 日期时间输入框组件 HTML 和日期输入框类似&#xff0c;日期时间输入框允许用户选择日期和指定的时间并按照指定的输出格式显示。相比日期输入框&#xff0c;它在下拉面板中添加了一个时间微调器。 <div class"topjui-containe…

使用oracle 的 PL/Sql 定时执行一个存储过程

/*使用oracle 的 PL/Sql 定时执行一个存储过程 测试目的&#xff1a;在表 tab 中间隔一分钟插入一条数据 实现方案&#xff1a;1.通过 oracle 中 dbms_job 完成存储过程的定时调用2.在存储过程中完成相应的逻辑操作 脚本说名&#xff1a;以下代码为 dbms_job 操作的基本写法&am…

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

在本文中&#xff0c;我将讨论JPA中的实体映射过程。 至于我的示例&#xff0c;我将使用与 我以前的一篇文章中使用的模式相同的模式 。 在前两篇文章中&#xff0c;我解释了如何在Java SE环境中设置JPA。 我不打算为Web应用程序编写安装过程&#xff0c;因为Web上的大多数教程…

table 设置边框

本文引自&#xff1a;https://www.cnblogs.com/leona-d/p/6125896.html 示例代码&#xff1a; <!DOCTYPE html><html lang"zh"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width…

uniapp小程序 设置自定义导航栏

如下截图&#xff0c;通过 wx.getSystemInfoSync 计算得到的整个导航栏高度&#xff0c;其实是有3个部分的&#xff1a; 黄色&#xff1a;状态栏高度&#xff0c;uniapp文档中有给出&#xff1b;红色&#xff1a;胶囊高度&#xff0c;可以计算得出&#xff1b;绿色&#xff1a;…

linux 下 的串口模拟器 minicom 退出方法

ctrl a &#xff08;或 A&#xff09; 进入 minicom 的配置模式&#xff1a;终端外观上无任何变化&#xff01; 然后按下 z &#xff08;或 Z&#xff09; 方可打开配置帮助界面 然后按下 x &#xff08;或 X&#xff09;退出转载于:https://www.cnblogs.com/jinzhenshui/p/11…

WebSpher 6.1 安装与应用

1. 名词术语解释1.1 名词缩写&#xff1a;1、 WAS&#xff1a; 即IBM公司的应用服务器WebSphere Application Server的简称&#xff1b;2、 ND&#xff1a; 即IBM公司的应用服务器WebSphere Application Server Network Deployment的简称&#xff1b;3、 IHS&#xff1a; 即IBM…

PostCSS 基本用法

1、postcss相关网站 https://www.postcss.com.cn/ https://www.ibm.com/developerworks/cn/web/1604-postcss-css/ 2、介绍 PostCSS 的主要功能只有两个&#xff1a;第一个就是前面提到的把 CSS 解析成 JavaScript 可以操作的 抽象语法树结构&#xff08;Abstract Syntax T…

Akka Notes –演员记录和测试

在前两部分&#xff08; 一 &#xff0c; 二 &#xff09;中&#xff0c;我们简要讨论了Actor以及消息传递的工作方式。 在这一部分中&#xff0c;让我们看一下如何修复并记录我们的TeacherActor 。 概括 这就是我们上一部分中的Actor的样子&#xff1a; class TeacherActor …

vue笔记(二)Vue-class与style、事件、计算属性、数据监听、指令+自定义指令、过滤器

vue官网 一 、class、style操作 二、事件 三、计算属性 四、数据监听、观测 五、指令自定义指令 六、过滤器 一 、class、style操作 官网 1. class使用&#xff1a; &#xff08;1&#xff09;v-bind:class“数据|属性|变量|表达式” &#xff08;2&#xff09;v-bind:class“…