JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-005控制类型映射(Nationalized、@LOB、@org.hibernate.annotations.Type)
2016-04-07 14:15
776 查看
一、简介
1.
2.
3.
4.
to override this default mapping. The JPA specification has a convenient shortcut annotation for this purpose, @Lob
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:
5.自定义类型
或
二、代码
三、测试代码
1.
2.
3.
4.
to override this default mapping. The JPA specification has a convenient shortcut annotation for this purpose, @Lob
@Entity public class Item { @Lob protected byte[] image; @Lob protected String description; // ... }
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:
@Entity public class Item { @Lob protected java.sql.Blob imageBlob; @Lob protected java.sql.Clob description; // ... }
5.自定义类型
@Entity public class Item { @org.hibernate.annotations.Type(type = "yes_no") protected boolean verified = false; }
或
metaBuilder.applyBasicType(new MyUserType(), new String[]{"date"});
二、代码
package org.jpwh.model.advanced; import org.jpwh.model.Constants; import javax.persistence.Access; import javax.persistence.AccessType; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Lob; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.sql.Blob; import java.util.Date; @Entity public class Item { /* The <code>Item</code> entity defaults to field access, the <code>@Id</code> is on a field. (We have also moved the brittle <code>ID_GENERATOR</code> string into a constant.) */ @Id @GeneratedValue(generator = Constants.ID_GENERATOR) protected Long id; @org.hibernate.annotations.Type(type = "yes_no") protected boolean verified = false; // JPA says @Temporal is required but Hibernate will default to TIMESTAMP without it @Temporal(TemporalType.TIMESTAMP) @Column(updatable = false) @org.hibernate.annotations.CreationTimestamp protected Date createdOn; // Java 8 API // protected Instant reviewedOn; @NotNull @Basic(fetch = FetchType.LAZY) // Defaults to EAGER protected String description; @Basic(fetch = FetchType.LAZY) @Column(length = 131072) // 128 kilobyte maximum for the picture protected byte[] image; // Maps to SQL VARBINARY type @Lob protected Blob imageBlob; @NotNull @Enumerated(EnumType.STRING) // Defaults to ORDINAL protected AuctionType auctionType = AuctionType.HIGHEST_BID; @org.hibernate.annotations.Formula( "substr(DESCRIPTION, 1, 12) || '...'" ) protected String shortDescription; @org.hibernate.annotations.Formula( "(select avg(b.AMOUNT) from BID b where b.ITEM_ID = ID)" ) protected BigDecimal averageBidAmount; @Column(name = "IMPERIALWEIGHT") @org.hibernate.annotations.ColumnTransformer( read = "IMPERIALWEIGHT / 2.20462", write = "? * 2.20462" ) protected double metricWeight; @Temporal(TemporalType.TIMESTAMP) @Column(insertable = false, updatable = false) @org.hibernate.annotations.Generated( org.hibernate.annotations.GenerationTime.ALWAYS ) protected Date lastModified; @Column(insertable = false) @org.hibernate.annotations.ColumnDefault("1.00") @org.hibernate.annotations.Generated( org.hibernate.annotations.GenerationTime.INSERT ) protected BigDecimal initialPrice; /* The <code>@Access(AccessType.PROPERTY)</code> setting on the <code>name</code> field switches this particular property to runtime access through getter/setter methods by the JPA provider. */ @Access(AccessType.PROPERTY) @Column(name = "ITEM_NAME") // Mappings are still expected here! protected String name; /* Hibernate will call <code>getName()</code> and <code>setName()</code> when loading and storing items. */ public String getName() { return name; } public void setName(String name) { this.name = !name.startsWith("AUCTION: ") ? "AUCTION: " + name : name; } public Long getId() { // Optional but useful return id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getShortDescription() { return shortDescription; } public BigDecimal getAverageBidAmount() { return averageBidAmount; } public double getMetricWeight() { return metricWeight; } public void setMetricWeight(double metricWeight) { this.metricWeight = metricWeight; } public Date getLastModified() { return lastModified; } public BigDecimal getInitialPrice() { return initialPrice; } public Date getCreatedOn() { return createdOn; } public boolean isVerified() { return verified; } public void setVerified(boolean verified) { this.verified = verified; } public byte[] getImage() { return image; } public void setImage(byte[] image) { this.image = image; } public Blob getImageBlob() { return imageBlob; } public void setImageBlob(Blob imageBlob) { this.imageBlob = imageBlob; } public AuctionType getAuctionType() { return auctionType; } public void setAuctionType(AuctionType auctionType) { this.auctionType = auctionType; } }
三、测试代码
package org.jpwh.test.advanced; import org.hibernate.Session; import org.hibernate.engine.jdbc.StreamUtils; import org.jpwh.env.JPATest; import org.jpwh.model.advanced.Item; import org.testng.annotations.Test; import javax.persistence.EntityManager; import javax.transaction.UserTransaction; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.sql.Blob; import java.util.Random; import static org.testng.Assert.assertEquals; public class LazyProperties extends JPATest { @Override public void configurePersistenceUnit() throws Exception { configurePersistenceUnit("AdvancedPU"); } @Test public void storeLoadProperties() throws Exception { UserTransaction tx = TM.getUserTransaction(); try { tx.begin(); EntityManager em = JPA.createEntityManager(); Item someItem = new Item(); someItem.setName("Some item"); someItem.setDescription("This is some description."); byte[] bytes = new byte[131072]; new Random().nextBytes(bytes); someItem.setImage(bytes); em.persist(someItem); tx.commit(); em.close(); Long ITEM_ID = someItem.getId(); tx.begin(); em = JPA.createEntityManager(); Item item = em.find(Item.class, ITEM_ID); // Accessing one initializes ALL lazy properties in a single SELECT assertEquals(item.getDescription(), "This is some description."); assertEquals(item.getImage().length, 131072); // 128 kilobytes tx.commit(); em.close(); } finally { TM.rollback(); } } @Test public void storeLoadLocator() throws Exception { // TODO: This test fails on H2 standalone // http://groups.google.com/group/h2-database/browse_thread/thread/9c6f4893a62c9b1a UserTransaction tx = TM.getUserTransaction(); try { tx.begin(); EntityManager em = JPA.createEntityManager(); byte[] bytes = new byte[131072]; new Random().nextBytes(bytes); InputStream imageInputStream = new ByteArrayInputStream(bytes); int byteLength = bytes.length; Item someItem = new Item(); someItem.setName("Some item"); someItem.setDescription("This is some description."); // Need the native Hibernate API Session session = em.unwrap(Session.class); // You need to know the number of bytes you want to read from the stream! Blob blob = session.getLobHelper() .createBlob(imageInputStream, byteLength); someItem.setImageBlob(blob); em.persist(someItem); tx.commit(); em.close(); Long ITEM_ID = someItem.getId(); tx.begin(); em = JPA.createEntityManager(); Item item = em.find(Item.class, ITEM_ID); // You can stream the bytes directly... InputStream imageDataStream = item.getImageBlob().getBinaryStream(); // ... or materialize them into memory: ByteArrayOutputStream outStream = new ByteArrayOutputStream(); StreamUtils.copy(imageDataStream, outStream); byte[] imageBytes = outStream.toByteArray(); assertEquals(imageBytes.length, 131072); tx.commit(); em.close(); } finally { TM.rollback(); } } }
<persistence-unit name="AdvancedPU"> <jta-data-source>myDS</jta-data-source> <class>org.jpwh.model</class> <class>org.jpwh.model.advanced.Item</class> <class>org.jpwh.model.advanced.Bid</class> <class>org.jpwh.model.advanced.User</class> <class>org.jpwh.model.advanced.Address</class> <class>org.jpwh.model.advanced.City</class> <class>org.jpwh.model.advanced.ItemBidSummary</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <!-- <properties> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> </properties> --> </persistence-unit>
相关文章推荐
- ImageView控件的基本用法
- Android ActionBar详解
- android studio下的NDK开发详解(一)
- iOS绘图 - 自定义柱状图绘制
- [Android]java.lang.OutOfMemoryError
- iOS8中的动态文本
- Android动画--Interpolator(插值器)
- Android 通过URL scheme 实现点击浏览器中的URL链接,启动特定的App,并调转页面传递参数
- android.support.v7包添加
- IOS开发之——CocoaPods安装和使用 OC和swift通吃
- Android 图片合成:添加蒙板效果 不规则相框 透明度渐变效果的实现
- Unity3d 读写文本
- Android Support 包里究竟有什么
- Android应用开发多语言drawable目录
- PHP开发APP接口
- 用Dagger2在Android中实现依赖注入
- Android Matrix理论与应用详解
- Android开源控件PhotoView的使用
- (转载)iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- iOS 打包ipa之Missing iOS Distribution signing identity问题