中山专业手机网站建设,二级建造师证报考要求,新的购物网站怎么做流量分析,上海公司建立网站吗在上一篇文章中#xff0c;我展示了一种持久保存实体的简单方法。 我解释了JPA用于确定实体默认表的默认方法。 假设我们要覆盖此默认名称。 我们之所以喜欢这样做#xff0c;是因为数据模型是以前设计和修复的#xff0c;并且表名与我们的类名不匹配#xff08;例如#… 在上一篇文章中我展示了一种持久保存实体的简单方法。 我解释了JPA用于确定实体默认表的默认方法。 假设我们要覆盖此默认名称。 我们之所以喜欢这样做是因为数据模型是以前设计和修复的并且表名与我们的类名不匹配例如我见过人们创建带有“ tbl_”前缀的表。 那么我们应该如何覆盖默认表名称以匹配现有数据模型 事实证明这非常简单。 如果我们需要覆盖JPA假定的默认表名则有两种方法可以做到 我们可以使用Entity批注的name属性来提供一个明确的实体名称以与数据库表名称匹配。 对于我们的示例如果表名是tbl_address则可以在Address类中使用Entityname “ tbl_address” 。 我们可以在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(namedocument_collection, schemadocument)
public class DocumentCollection {// rest of the class
} 当以这种方式指定时就像我们在查询中所做的那样当JPA进入数据库以访问表时架构名称将作为表名称的前缀添加。 如果不是在 Table批注中指定架构名称而是在表名称本身中附加了架构名称该怎么办呢 Entity
Table(name document.document_collection)
public class DocumentCollection {// rest of the class
} 不能保证以这种方式将模式名称与表名称内联因为在JPA规范非标准中未指定对此名称的支持。 因此即使您的持久性提供程序支持它也最好不要养成这样做的习惯。 接下来我们将注意力转移到各列。 为了确定默认列JPA进行了类似于以下操作 首先它检查是否给出了任何显式的列映射信息。 如果找不到列映射信息它将尝试猜测列的默认值。 为了确定默认值JPA需要知道实体状态的访问类型即读取/写入实体状态的方式。 在JPA中两种不同的访问类型是可能的-字段和属性。 在我们的示例中我们使用了字段访问实际上JPA从Id批注的位置/位置假定了这一点但稍后会对此进行更多介绍。 如果您使用此访问类型则将使用Reflection API从实体字段直接写入/读取状态。 知道访问类型后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 {IdGeneratedValueColumn(name address_id)private Integer id;// Rest of the class
} 您可以看到对于上述所有情况JPA使用的默认方法都非常明智大多数情况下您都会对此感到满意。 但是更改默认值也很容易并且可以很快完成。 如果我们在地址实体中有一个不希望保存在数据库中的字段怎么办 假设Address实体有一个名为transientColumn的列该列在数据库表中没有任何对应的默认列 Entity
Table(name tbl_address)
public class Address {IdGeneratedValueColumn(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的列 并且我们没有采取任何措施使持久性提供程序明确表示我们不希望将此字段保存在数据库中。 持久性提供程序将其用作实体中映射到数据库列的任何其他字段。 为了解决此问题我们可以执行以下任一操作 我们可以使用Transient 在javax.persistence包中定义注解来对transientColumn字段进行注解以使持久性提供程序知道我们不希望保存该字段并且该表中没有任何对应的列。 我们可以使用Java默认具有的transient关键字。 我想到的这两种方法之间的区别在于如果我们使用transient关键字而不是annotation则如果Address对象之一从一个JVM序列化到另一个JVM那么transitionColumn字段将再次被重新初始化就像Java中的其他任何临时字段。 对于注释这不会发生并且transientColumn字段将在序列化过程中保留其值。 根据经验如果我不需要担心序列化在大多数情况下不需要我总是使用批注。 因此使用注释我们可以立即解决问题 Entity
Table(name tbl_address)
public class Address {IdGeneratedValueColumn(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