JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-003映射实体时的可选操作(<delimited-identifiers/>、PhysicalNamingStrategy、PhysicalNamingStrategyStandardImpl、、、)

一、自定义映射的表名

1.

1 @Entity
2 @Table(name = "USERS")
3 public class User implements Serializable {
4     // ...
5 }

 

2.用定界符

1 //@Table(name = "`USER`")的标准
2 @Table(name = "`USER`")
3 
4 //JPA的标准
5 @Table(name = "\"USER\"")

若全部SQL都加定界符, create an orm.xml file and add the setting <delimited-identifiers/> to its <persistence-unit-defaults> section,Hibernate then enforces quoted identifiers everywhere.

 

3.若要映射的表都有前缀,则可用实现PhysicalNamingStrategy接口或继承已有的实现

 1 package org.jpwh.shared;
 2 
 3 import org.hibernate.boot.model.naming.Identifier;
 4 import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
 5 
 6 /**
 7  * Prefixes all SQL table names with "CE_", for CaveatEmptor.
 8  */
 9 public class CENamingStrategy extends
10     org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl {
11 
12     @Override
13     public Identifier toPhysicalTableName(Identifier name,
14                                           JdbcEnvironment context) {
15         return new Identifier("CE_" + name.getText(), name.isQuoted());
16     }
17 
18 }

You have to enable the naming-strategy implementation in persistence.xml:

1 <persistence-unit>name="CaveatEmptorPU"> 
2     ...
3     <properties>
4         <property name="hibernate.physical_naming_strategy" value="org.jpwh.shared.CENamingStrategy" />
5     </properties>
6 </persistence-unit>

 

4.用ImplicitNamingStrategy

 

二、自定义实体名

1.

1 package my.other.model;
2 @javax.persistence.Entity(name = "AuctionItem")
3 public class Item {
4     // ...
5 }

 

三、动态生成SQL

To disable generation of INSERT and UPDATE SQL statements on startup, you need native Hibernate annotations:

1 @Entity
2 @org.hibernate.annotations.DynamicInsert
3 @org.hibernate.annotations.DynamicUpdate
4 public class Item {
5     // ...
6 }

 

四、实体相关选项

1.Making an entity immutable

1 @Entity
2 @org.hibernate.annotations.Immutable
3 public class Bid {
4     // ...
5 }

 

2.Mapping an entity to a subselect

 

When an instance of ItemBidSummary is loaded, Hibernate executes your custom SQL
SELECT as a subselect:

 

 

Synchronize注解的作用:Hibernate will then know it has to flush modifications of Item and Bid instances
before it executes a query against ItemBidSummary

 

 1 package org.jpwh.model.advanced;
 2 
 3 import javax.persistence.Entity;
 4 import javax.persistence.Id;
 5 
 6 @Entity
 7 @org.hibernate.annotations.Immutable
 8 @org.hibernate.annotations.Subselect(
 9     value = "select i.ID as ITEMID, i.ITEM_NAME as NAME, " +
10             "count(b.ID) as NUMBEROFBIDS " +
11             "from ITEM i left outer join BID b on i.ID = b.ITEM_ID " +
12             "group by i.ID, i.ITEM_NAME"
13 )
14 
15 // TODO Table names are case sensitive, Hibernate bug HHH-8430
16 @org.hibernate.annotations.Synchronize({"Item", "Bid"})
17 public class ItemBidSummary {
18 
19     @Id
20     protected Long itemId;
21 
22     protected String name;
23 
24     protected long numberOfBids;
25 
26     public ItemBidSummary() {
27     }
28 
29     // Getter methods...
30     public Long getItemId() {
31         return itemId;
32     }
33 
34     public String getName() {
35         return name;
36     }
37 
38     public long getNumberOfBids() {
39         return numberOfBids;
40     }
41 
42     // ...
43 }

 

五、测试代码

1.

 1 package org.jpwh.test.advanced;
 2 
 3 import org.jpwh.env.JPATest;
 4 import org.jpwh.model.advanced.Bid;
 5 import org.jpwh.model.advanced.Item;
 6 import org.jpwh.model.advanced.ItemBidSummary;
 7 import org.testng.annotations.Test;
 8 
 9 import javax.persistence.EntityManager;
10 import javax.persistence.Query;
11 import javax.transaction.UserTransaction;
12 import java.math.BigDecimal;
13 
14 import static org.testng.Assert.assertEquals;
15 
16 public class MappedSubselect extends JPATest {
17 
18     @Override
19     public void configurePersistenceUnit() throws Exception {
20         configurePersistenceUnit("AdvancedPU");
21     }
22 
23     @Test
24     public void loadSubselectEntity() throws Exception {
25         long ITEM_ID = storeItemAndBids();
26 
27         UserTransaction tx = TM.getUserTransaction();
28         try {
29             tx.begin();
30             EntityManager em = JPA.createEntityManager();
31 
32             {
33                 ItemBidSummary itemBidSummary = em.find(ItemBidSummary.class, ITEM_ID);
34                 // select * from (
35                 //      select i.ID as ITEMID, i.ITEM_NAME as NAME, ...
36                 // ) where ITEMID = ?
37 
38                 assertEquals(itemBidSummary.getName(), "AUCTION: Some item");
39             }
40             em.clear();
41 
42             { // Hibernate will synchronize the right tables before querying
43                 Item item = em.find(Item.class, ITEM_ID);
44                 item.setName("New name");
45 
46                 // No flush before retrieval by identifier!
47                  //ItemBidSummary itemBidSummary = em.find(ItemBidSummary.class, ITEM_ID);
48 
49                 // Automatic flush before queries if synchronized tables are affected!
50                 Query query = em.createQuery(
51                     "select ibs from ItemBidSummary ibs where ibs.itemId = :id"
52                 );
53                 ItemBidSummary itemBidSummary =
54                     (ItemBidSummary)query.setParameter("id", ITEM_ID).getSingleResult();
55 
56                 assertEquals(itemBidSummary.getName(), "AUCTION: New name");
57             }
58 
59             tx.commit();
60             em.close();
61         } finally {
62             TM.rollback();
63         }
64     }
65 
66     public Long storeItemAndBids() throws Exception {
67         UserTransaction tx = TM.getUserTransaction();
68         tx.begin();
69         EntityManager em = JPA.createEntityManager();
70         Item item = new Item();
71         item.setName("Some item");
72         item.setDescription("This is some description.");
73         em.persist(item);
74         for (int i = 1; i <= 3; i++) {
75             Bid bid = new Bid();
76             bid.setAmount(new BigDecimal(10 + i));
77             bid.setItem(item);
78             em.persist(bid);
79         }
80         tx.commit();
81         em.close();
82         return item.getId();
83     }
84 
85 }

 Note that Hibernate doesn’t flush automatically before a find() operation—only before a Query is executed, if necessary. Hibernate detects that the modified Item will affect the result of the query, because the ITEM table is synchronized with ItemBid-Summary . Hence, a flush and the UPDATE of the ITEM row are necessary to avoid the

query returning stale data.

2.

  1 package org.jpwh.model.advanced;
  2 
  3 import org.jpwh.model.Constants;
  4 
  5 import javax.persistence.Access;
  6 import javax.persistence.AccessType;
  7 import javax.persistence.Basic;
  8 import javax.persistence.Column;
  9 import javax.persistence.Entity;
 10 import javax.persistence.EnumType;
 11 import javax.persistence.Enumerated;
 12 import javax.persistence.FetchType;
 13 import javax.persistence.GeneratedValue;
 14 import javax.persistence.Id;
 15 import javax.persistence.Lob;
 16 import javax.persistence.Temporal;
 17 import javax.persistence.TemporalType;
 18 import javax.validation.constraints.NotNull;
 19 import java.math.BigDecimal;
 20 import java.sql.Blob;
 21 import java.util.Date;
 22 
 23 @Entity
 24 public class Item {
 25 
 26     /* 
 27        The <code>Item</code> entity defaults to field access, the <code>@Id</code> is on a field. (We
 28        have also moved the brittle <code>ID_GENERATOR</code> string into a constant.)
 29      */
 30     @Id
 31     @GeneratedValue(generator = Constants.ID_GENERATOR)
 32     protected Long id;
 33 
 34     @org.hibernate.annotations.Type(type = "yes_no")
 35     protected boolean verified = false;
 36 
 37     // JPA says @Temporal is required but Hibernate will default to TIMESTAMP without it
 38     @Temporal(TemporalType.TIMESTAMP)
 39     @Column(updatable = false)
 40     @org.hibernate.annotations.CreationTimestamp
 41     protected Date createdOn;
 42 
 43     // Java 8 API
 44     // protected Instant reviewedOn;
 45 
 46     @NotNull
 47     @Basic(fetch = FetchType.LAZY) // Defaults to EAGER
 48     protected String description;
 49 
 50     @Basic(fetch = FetchType.LAZY)
 51     @Column(length = 131072) // 128 kilobyte maximum for the picture
 52     protected byte[] image; // Maps to SQL VARBINARY type
 53 
 54     @Lob
 55     protected Blob imageBlob;
 56 
 57     @NotNull
 58     @Enumerated(EnumType.STRING) // Defaults to ORDINAL
 59     protected AuctionType auctionType = AuctionType.HIGHEST_BID;
 60 
 61     @org.hibernate.annotations.Formula(
 62         "substr(DESCRIPTION, 1, 12) || '...'"
 63     )
 64     protected String shortDescription;
 65 
 66     @org.hibernate.annotations.Formula(
 67         "(select avg(b.AMOUNT) from BID b where b.ITEM_ID = ID)"
 68     )
 69     protected BigDecimal averageBidAmount;
 70 
 71     @Column(name = "IMPERIALWEIGHT")
 72     @org.hibernate.annotations.ColumnTransformer(
 73         read = "IMPERIALWEIGHT / 2.20462",
 74         write = "? * 2.20462"
 75     )
 76     protected double metricWeight;
 77 
 78     @Temporal(TemporalType.TIMESTAMP)
 79     @Column(insertable = false, updatable = false)
 80     @org.hibernate.annotations.Generated(
 81         org.hibernate.annotations.GenerationTime.ALWAYS
 82     )
 83     protected Date lastModified;
 84 
 85     @Column(insertable = false)
 86     @org.hibernate.annotations.ColumnDefault("1.00")
 87     @org.hibernate.annotations.Generated(
 88         org.hibernate.annotations.GenerationTime.INSERT
 89     )
 90     protected BigDecimal initialPrice;
 91 
 92     /* 
 93         The <code>@Access(AccessType.PROPERTY)</code> setting on the <code>name</code> field switches this
 94         particular property to runtime access through getter/setter methods by the JPA provider.
 95      */
 96     @Access(AccessType.PROPERTY)
 97     @Column(name = "ITEM_NAME") // Mappings are still expected here!
 98     protected String name;
 99 
100     /* 
101         Hibernate will call <code>getName()</code> and <code>setName()</code> when loading and storing items.
102      */
103     public String getName() {
104         return name;
105     }
106 
107     public void setName(String name) {
108         this.name =
109             !name.startsWith("AUCTION: ") ? "AUCTION: " + name : name;
110     }
111 
112     public Long getId() { // Optional but useful
113         return id;
114     }
115 
116     public String getDescription() {
117         return description;
118     }
119 
120     public void setDescription(String description) {
121         this.description = description;
122     }
123 
124     public String getShortDescription() {
125         return shortDescription;
126     }
127 
128     public BigDecimal getAverageBidAmount() {
129         return averageBidAmount;
130     }
131 
132     public double getMetricWeight() {
133         return metricWeight;
134     }
135 
136     public void setMetricWeight(double metricWeight) {
137         this.metricWeight = metricWeight;
138     }
139 
140     public Date getLastModified() {
141         return lastModified;
142     }
143 
144     public BigDecimal getInitialPrice() {
145         return initialPrice;
146     }
147 
148     public Date getCreatedOn() {
149         return createdOn;
150     }
151 
152     public boolean isVerified() {
153         return verified;
154     }
155 
156     public void setVerified(boolean verified) {
157         this.verified = verified;
158     }
159 
160     public byte[] getImage() {
161         return image;
162     }
163 
164     public void setImage(byte[] image) {
165         this.image = image;
166     }
167 
168     public Blob getImageBlob() {
169         return imageBlob;
170     }
171 
172     public void setImageBlob(Blob imageBlob) {
173         this.imageBlob = imageBlob;
174     }
175 
176     public AuctionType getAuctionType() {
177         return auctionType;
178     }
179 
180     public void setAuctionType(AuctionType auctionType) {
181         this.auctionType = auctionType;
182     }
183 }

 

3.

 1 package org.jpwh.model.advanced;
 2 
 3 import org.jpwh.model.Constants;
 4 
 5 import javax.persistence.Entity;
 6 import javax.persistence.FetchType;
 7 import javax.persistence.GeneratedValue;
 8 import javax.persistence.Id;
 9 import javax.persistence.JoinColumn;
10 import javax.persistence.ManyToOne;
11 import javax.validation.constraints.NotNull;
12 import java.math.BigDecimal;
13 
14 @Entity
15 @org.hibernate.annotations.Immutable
16 public class Bid {
17 
18     @Id
19     @GeneratedValue(generator = Constants.ID_GENERATOR)
20     protected Long id;
21 
22     @NotNull
23     protected BigDecimal amount;
24 
25     @ManyToOne(optional = false, fetch = FetchType.LAZY) // NOT NULL
26     @JoinColumn(name = "ITEM_ID") // Actually the default name
27     protected Item item;
28 
29     public Long getId() {
30         return id;
31     }
32 
33     public BigDecimal getAmount() {
34         return amount;
35     }
36 
37     public void setAmount(BigDecimal amount) {
38         this.amount = amount;
39     }
40 
41     public Item getItem() {
42         return item;
43     }
44 
45     public void setItem(Item item) {
46         this.item = item;
47     }
48 }

 

posted @ 2016-04-04 14:09  shamgod  阅读(2507)  评论(0编辑  收藏  举报
haha