jpa 实体映射视图_JPA教程:实体映射-第2部分
jpa 實體映射視圖
在上一篇文章中,我展示了一種持久保存實體的簡單方法。 我解釋了JPA用于確定實體默認表的默認方法。 假設我們要覆蓋此默認名稱。 我們之所以喜歡這樣做,是因為數據模型是以前設計和修復的,并且表名與我們的類名不匹配(例如,我見過人們創建帶有“ tbl_”前綴的表)。 那么我們應該如何覆蓋默認表名稱以匹配現有數據模型?
事實證明,這非常簡單。 如果我們需要覆蓋JPA假定的默認表名,則有兩種方法可以做到:
通過這兩種方法,@ Table批注提供了更多用于自定義映射的選項。 例如,某些數據庫(例如PostgreSQL)具有schemas概念,您可以使用schemas進一步對表進行分類/分組。 由于此功能,您可以在一個數據庫中創建兩個具有相同名稱的表(盡管它們將屬于兩個不同的模式)。 要訪問這些表,然后在查詢中添加架構名稱作為表前綴。 因此,如果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進行了類似于以下操作:
至此,我們應該很清楚地址實體的狀態如何保存到相應的列中。 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的列 ,并且我們沒有采取任何措施使持久性提供程序明確表示我們不希望將此字段保存在數據庫中。 持久性提供程序將其用作實體中映射到數據庫列的任何其他字段。
為了解決此問題,我們可以執行以下任一操作:
我想到的這兩種方法之間的區別在于,如果我們使用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 實體映射視圖
總結
以上是生活随笔為你收集整理的jpa 实体映射视图_JPA教程:实体映射-第2部分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三星安卓平板强制横屏(三星安卓平板)
- 下一篇: Java:ChronicleMap第2部