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 ...
随机推荐
- Mono for Android (1) 之布局
最近和同事交接工作,首次接触mono for android, 结果画view时少了layout,页面没办法出来,各种冥思,各种找问题,最后把关于布局的一些共享出来(同事写的,哈哈): Andro ...
- java中字符串String 转 int(转)
java中字符串String 转 int String -> int s="12345"; int i; 第一种方法:i=Integer.parseInt(s); 第二种方法 ...
- 骇客(Hacker)用语
什么是TCP/IP 是一种网络通信协议,他规范了网络上所有的通信设备,尤其是一个主机与另一个主机之间的数据往来格式以及传送方式.,TCP/IP是INTERNET的基础 ...
- [shell基础]——paste命令
测试文本内容如下: # cat name1.txt name1 alvin1 name2 alvin2 name3 alvin3 name4 alvin4 # cat name2.txt name1 ...
- C#和asp.net执行外部EXE程序
这两天研究下.Net的执行外部EXE程序问题,就是在一个程序里通过按钮或其他操作运行起来另外一个程序,需要传入参数,如用户名.密码之类(实际上很类似单点登录,不过要简单的多的多):总结如下: 1.CS ...
- Codeforces Round #131 (Div. 1) B. Numbers dp
题目链接: http://codeforces.com/problemset/problem/213/B B. Numbers time limit per test 2 secondsmemory ...
- 版本控制 - Git
此篇blog只是对http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 研读后的总结,还 ...
- max_flow(Ford-Fulkerson) 分类: ACM TYPE 2014-09-02 01:50 110人阅读 评论(0) 收藏
#include <cstdio> #include <iostream> #include <cstring> #include<queue> usi ...
- css两个form不换行,两个div并排代码
1.form不换行通过table布局实现 <table> <tr> <td> <form method="get" action=&quo ...
- Using the viewport meta tag to control layout on mobile browsers
A typical mobile-optimized site contains something like the following: <meta name="viewport& ...