JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-003映射实体时的可选操作(<delimited-identifiers/>、PhysicalNamingStrategy、PhysicalNamingStrategyStandardImpl、、、)
一、自定义映射的表名
1.
@Entity
@Table(name = "USERS")
public class User implements Serializable {
// ...
}
2.用定界符
//@Table(name = "`USER`")的标准
@Table(name = "`USER`") //JPA的标准
@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接口或继承已有的实现
package org.jpwh.shared; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; /**
* Prefixes all SQL table names with "CE_", for CaveatEmptor.
*/
public class CENamingStrategy extends
org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl { @Override
public Identifier toPhysicalTableName(Identifier name,
JdbcEnvironment context) {
return new Identifier("CE_" + name.getText(), name.isQuoted());
} }
You have to enable the naming-strategy implementation in persistence.xml:
<persistence-unit>name="CaveatEmptorPU">
...
<properties>
<property name="hibernate.physical_naming_strategy" value="org.jpwh.shared.CENamingStrategy" />
</properties>
</persistence-unit>
4.用ImplicitNamingStrategy
二、自定义实体名
1.
package my.other.model;
@javax.persistence.Entity(name = "AuctionItem")
public class Item {
// ...
}
三、动态生成SQL
To disable generation of INSERT and UPDATE SQL statements on startup, you need native Hibernate annotations:
@Entity
@org.hibernate.annotations.DynamicInsert
@org.hibernate.annotations.DynamicUpdate
public class Item {
// ...
}
四、实体相关选项
1.Making an entity immutable
@Entity
@org.hibernate.annotations.Immutable
public class Bid {
// ...
}
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
package org.jpwh.model.advanced; import javax.persistence.Entity;
import javax.persistence.Id; @Entity
@org.hibernate.annotations.Immutable
@org.hibernate.annotations.Subselect(
value = "select i.ID as ITEMID, i.ITEM_NAME as NAME, " +
"count(b.ID) as NUMBEROFBIDS " +
"from ITEM i left outer join BID b on i.ID = b.ITEM_ID " +
"group by i.ID, i.ITEM_NAME"
) // TODO Table names are case sensitive, Hibernate bug HHH-8430
@org.hibernate.annotations.Synchronize({"Item", "Bid"})
public class ItemBidSummary { @Id
protected Long itemId; protected String name; protected long numberOfBids; public ItemBidSummary() {
} // Getter methods...
public Long getItemId() {
return itemId;
} public String getName() {
return name;
} public long getNumberOfBids() {
return numberOfBids;
} // ...
}
五、测试代码
1.
package org.jpwh.test.advanced; import org.jpwh.env.JPATest;
import org.jpwh.model.advanced.Bid;
import org.jpwh.model.advanced.Item;
import org.jpwh.model.advanced.ItemBidSummary;
import org.testng.annotations.Test; import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.UserTransaction;
import java.math.BigDecimal; import static org.testng.Assert.assertEquals; public class MappedSubselect extends JPATest { @Override
public void configurePersistenceUnit() throws Exception {
configurePersistenceUnit("AdvancedPU");
} @Test
public void loadSubselectEntity() throws Exception {
long ITEM_ID = storeItemAndBids(); UserTransaction tx = TM.getUserTransaction();
try {
tx.begin();
EntityManager em = JPA.createEntityManager(); {
ItemBidSummary itemBidSummary = em.find(ItemBidSummary.class, ITEM_ID);
// select * from (
// select i.ID as ITEMID, i.ITEM_NAME as NAME, ...
// ) where ITEMID = ? assertEquals(itemBidSummary.getName(), "AUCTION: Some item");
}
em.clear(); { // Hibernate will synchronize the right tables before querying
Item item = em.find(Item.class, ITEM_ID);
item.setName("New name"); // No flush before retrieval by identifier!
//ItemBidSummary itemBidSummary = em.find(ItemBidSummary.class, ITEM_ID); // Automatic flush before queries if synchronized tables are affected!
Query query = em.createQuery(
"select ibs from ItemBidSummary ibs where ibs.itemId = :id"
);
ItemBidSummary itemBidSummary =
(ItemBidSummary)query.setParameter("id", ITEM_ID).getSingleResult(); assertEquals(itemBidSummary.getName(), "AUCTION: New name");
} tx.commit();
em.close();
} finally {
TM.rollback();
}
} public Long storeItemAndBids() throws Exception {
UserTransaction tx = TM.getUserTransaction();
tx.begin();
EntityManager em = JPA.createEntityManager();
Item item = new Item();
item.setName("Some item");
item.setDescription("This is some description.");
em.persist(item);
for (int i = 1; i <= 3; i++) {
Bid bid = new Bid();
bid.setAmount(new BigDecimal(10 + i));
bid.setItem(item);
em.persist(bid);
}
tx.commit();
em.close();
return item.getId();
} }
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.
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;
}
}
3.
package org.jpwh.model.advanced; import org.jpwh.model.Constants; import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal; @Entity
@org.hibernate.annotations.Immutable
public class Bid { @Id
@GeneratedValue(generator = Constants.ID_GENERATOR)
protected Long id; @NotNull
protected BigDecimal amount; @ManyToOne(optional = false, fetch = FetchType.LAZY) // NOT NULL
@JoinColumn(name = "ITEM_ID") // Actually the default name
protected Item item; public Long getId() {
return id;
} public BigDecimal getAmount() {
return amount;
} public void setAmount(BigDecimal amount) {
this.amount = amount;
} public Item getItem() {
return item;
} public void setItem(Item item) {
this.item = item;
}
}
JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-003映射实体时的可选操作(<delimited-identifiers/>、PhysicalNamingStrategy、PhysicalNamingStrategyStandardImpl、、、)的更多相关文章
- JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-002identity详解
一.简介 1.You now have three methods for distinguishing references: Objects are identical if they occ ...
- JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-001区分entities and value types
一.介绍 1.这种引用方式不对,但删除时不能级联 要这种引用方式 2.The Bid class could be a problem. In object-oriented modeling, th ...
- 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 a ...
- JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-001Mapping basic properties(@Basic、@Access、access="noop"、@Formula、@ColumnTransformer、@Generated、 @ColumnDefaul、@Temporal、@Enumerated)
一.简介 在JPA中,默认所有属性都会persist,属性要属于以下3种情况,Hibernate在启动时会报错 1.java基本类型或包装类 2.有注解 @Embedded 3.有实现java.io. ...
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-006Mixing inheritance strategies(@SecondaryTable、@PrimaryKeyJoinColumn、<join fetch="select">)
一.结构 For example, you can map a class hierarchy to a single table, but, for a particular subclass, s ...
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-003Table per concrete class with unions(@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)、<union-subclass>)
一.代码 1. package org.jpwh.model.inheritance.tableperclass; import org.jpwh.model.Constants; import ja ...
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-002Table per concrete class with implicit polymorphism(@MappedSuperclass、@AttributeOverride)
一.结构 二.代码 1. package org.jpwh.model.inheritance.mappedsuperclass; import javax.persistence.MappedSup ...
- JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-007UserTypes的用法(@org.hibernate.annotations.Type、@org.hibernate.annotations.TypeDefs、CompositeUserType、DynamicParameterizedType、、、)
一.结构 二.Hibernate支持的UserTypes接口 UserType —You can transform values by interacting with the plain JD ...
- JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-006类型转换器( @Converter(autoApply = true) 、type="converter:qualified.ConverterName" )
一.结构 二.代码 1. package org.jpwh.model.advanced; import java.io.Serializable; import java.math.BigDecim ...
随机推荐
- Python实现SVM(支持向量机)
Python实现SVM(支持向量机) 运行环境 Pyhton3 numpy(科学计算包) matplotlib(画图所需,不画图可不必) 计算过程 st=>start: 开始 e=>end ...
- Mono for Android (2)-- Android应用程序初认识
一:日志记录 先添加using Android.Util; 在该命名控件下有log类 Log.Info("HA", "End onCreate"); //记录消 ...
- Net Core 的公共组件之 Http 请求客户端
Net Core 的公共组件之 Http 请求客户端 想必大家在项目开发的时候应该都在程序中调用过自己内部的接口或者使用过第三方提供的接口,咱今天不讨论 REST ,最常用的请求应该就是 GET 和 ...
- BZOJ 4500: 矩阵 差分约束
题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=4500 题解: 从行向列建边,代表一个格子a[i][j],对每个顶点的所有操作可以合并在一 ...
- HDU 5693 D Game 区间dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5693 题解: 一种朴实的想法是枚举选择可以删除的两个或三个数(其他的大于三的数都能凑成2和3的和), ...
- map初始化定时器
init_timer(); //各种定时器的初始化 void Map::init_timer() { //auto tf = GetPlug(TimerFactory); auto tf = m_sp ...
- 引擎设计跟踪(九.14.2a) 导出插件问题修复和 Tangent Space 裂缝修复
由于工作很忙, 近半年的业余时间没空搞了, 不过工作马上忙完了, 趁十一有时间修了一些小问题. 这次更新跟骨骼动画无关, 修复了一个之前的, 关于tangent space裂缝的问题: 引擎设计跟踪( ...
- spring mvc注解@RequestParam
在spring mvc 的使用过程中 获取 页面传来的参数的时候,我平时都习惯 @RequestParam String name,突然有一天我发现 直接在方法参数后面写 String name , ...
- 2014年03月09日攻击百度贴吧的XSS蠕虫源码
var n=PageData.user.user_forum_list.info.length; var num=0; var config = { titles: ["\u4f60\u76 ...
- UglifyJS--javascript代码压缩使用指南{转}
在线测试地址 http://lisperator.net/uglifyjs/下面都是基于linux系统的安装使用.UglifyJS是遵循了CommonJS规范写成的,可以在支持CommonJS模块系统 ...