JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-005控制类型映射(Nationalized、@LOB、@org.hibernate.annotations.Type)

一、简介

1.

2.

3.

4.

 

to override this default mapping. The JPA specification has a convenient shortcut annotation for this purpose, @Lob

1 @Entity
2 public class Item {
3     @Lob
4     protected byte[] image;
5     @Lob
6     protected String description;
7     // ...
8 }

This maps the byte[] to an SQL BLOB data type and the String to a CLOB . Unfortunately, you still don’t get lazy loading with this design.

Alternatively, you can switch the type of property in your Java class. JDBC supports locator objects ( LOB s) directly. If your Java property is java.sql.Clob or java .sql.Blob , you get lazy loading without bytecode instrumentation:

1 @Entity
2 public class Item {
3     @Lob
4     protected java.sql.Blob imageBlob;
5     @Lob
6     protected java.sql.Clob description;
7     // ...
8 }

 

 5.自定义类型

1 @Entity
2 public class Item {
3     @org.hibernate.annotations.Type(type = "yes_no")
4     protected boolean verified = false;
5 }

1 metaBuilder.applyBasicType(new MyUserType(), new String[]{"date"});

 

二、代码

  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 }

 

三、测试代码

  1 package org.jpwh.test.advanced;
  2 
  3 import org.hibernate.Session;
  4 import org.hibernate.engine.jdbc.StreamUtils;
  5 import org.jpwh.env.JPATest;
  6 import org.jpwh.model.advanced.Item;
  7 import org.testng.annotations.Test;
  8 
  9 import javax.persistence.EntityManager;
 10 import javax.transaction.UserTransaction;
 11 import java.io.ByteArrayInputStream;
 12 import java.io.ByteArrayOutputStream;
 13 import java.io.InputStream;
 14 import java.sql.Blob;
 15 import java.util.Random;
 16 
 17 import static org.testng.Assert.assertEquals;
 18 
 19 public class LazyProperties extends JPATest {
 20 
 21     @Override
 22     public void configurePersistenceUnit() throws Exception {
 23         configurePersistenceUnit("AdvancedPU");
 24     }
 25 
 26     @Test
 27     public void storeLoadProperties() throws Exception {
 28         UserTransaction tx = TM.getUserTransaction();
 29         try {
 30             tx.begin();
 31             EntityManager em = JPA.createEntityManager();
 32             Item someItem = new Item();
 33             someItem.setName("Some item");
 34             someItem.setDescription("This is some description.");
 35             byte[] bytes = new byte[131072];
 36             new Random().nextBytes(bytes);
 37             someItem.setImage(bytes);
 38             em.persist(someItem);
 39             tx.commit();
 40             em.close();
 41             Long ITEM_ID = someItem.getId();
 42 
 43             tx.begin();
 44             em = JPA.createEntityManager();
 45 
 46             Item item = em.find(Item.class, ITEM_ID);
 47 
 48             // Accessing one initializes ALL lazy properties in a single SELECT
 49             assertEquals(item.getDescription(), "This is some description.");
 50             assertEquals(item.getImage().length, 131072); // 128 kilobytes
 51 
 52             tx.commit();
 53             em.close();
 54         } finally {
 55             TM.rollback();
 56         }
 57     }
 58 
 59     @Test
 60     public void storeLoadLocator() throws Exception {
 61         // TODO: This test fails on H2 standalone
 62         // http://groups.google.com/group/h2-database/browse_thread/thread/9c6f4893a62c9b1a
 63         UserTransaction tx = TM.getUserTransaction();
 64         try {
 65             tx.begin();
 66             EntityManager em = JPA.createEntityManager();
 67 
 68             byte[] bytes = new byte[131072];
 69             new Random().nextBytes(bytes);
 70             InputStream imageInputStream = new ByteArrayInputStream(bytes);
 71             int byteLength = bytes.length;
 72 
 73             Item someItem = new Item();
 74             someItem.setName("Some item");
 75             someItem.setDescription("This is some description.");
 76 
 77             // Need the native Hibernate API
 78             Session session = em.unwrap(Session.class);
 79             // You need to know the number of bytes you want to read from the stream!
 80             Blob blob = session.getLobHelper()
 81                     .createBlob(imageInputStream, byteLength);
 82 
 83             someItem.setImageBlob(blob);
 84             em.persist(someItem);
 85 
 86             tx.commit();
 87             em.close();
 88 
 89             Long ITEM_ID = someItem.getId();
 90 
 91             tx.begin();
 92             em = JPA.createEntityManager();
 93 
 94             Item item = em.find(Item.class, ITEM_ID);
 95 
 96             // You can stream the bytes directly...
 97             InputStream imageDataStream = item.getImageBlob().getBinaryStream();
 98 
 99             // ... or materialize them into memory:
100             ByteArrayOutputStream outStream = new ByteArrayOutputStream();
101             StreamUtils.copy(imageDataStream, outStream);
102             byte[] imageBytes = outStream.toByteArray();
103             assertEquals(imageBytes.length, 131072);
104 
105             tx.commit();
106             em.close();
107         } finally {
108             TM.rollback();
109         }
110     }
111 
112 
113 }

 

 1 <persistence-unit name="AdvancedPU">
 2         <jta-data-source>myDS</jta-data-source>
 3         <class>org.jpwh.model</class>
 4         <class>org.jpwh.model.advanced.Item</class>
 5         <class>org.jpwh.model.advanced.Bid</class>
 6         <class>org.jpwh.model.advanced.User</class>
 7         <class>org.jpwh.model.advanced.Address</class>
 8         <class>org.jpwh.model.advanced.City</class>
 9         <class>org.jpwh.model.advanced.ItemBidSummary</class>
10         <exclude-unlisted-classes>true</exclude-unlisted-classes>
11         <!-- 
12         <properties>
13             <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
14         </properties>
15         -->
16     </persistence-unit>

 

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