您的位置:首页 > 移动开发

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

@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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: