JavaPersistenceWithHibernate第二版笔记Getting started with ORM-002Domain层详解及M etaModel

一、结构

 

 

 

二、配置文件约定

The JPA provider automatically picks up this descriptor if you place it in a META-INF /orm.xml file on the classpath of the persistence unit. If you prefer to use a different name or several files, you’ll have to change the configuration of the persistence unit in your META-INF /persistence.xml file:

If you include the <xml-mapping-metadata-complete> element, the JPA provider ignores all annotations on your domain model classes in this persistence unit and relies only on the mappings as defined in the XML descriptor(s). You can (redundantly in this case) enable this on an entity level, with <metadata-complete="true"/> . If enabled, the JPA provider assumes that you mapped all attributes of the entity in XML and that it should ignore all annotations for this particular entity.

 

1.Mappings.xml

 1 <entity-mappings
 2         version="2.1"
 3         xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
 4         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
 6             http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
 7 
 8     <!-- First, global metadata -->
 9     <persistence-unit-metadata>
10 
11         <!-- Ignore all annotations, all mapping metadata in XML files -->
12         <xml-mapping-metadata-complete/>
13 
14         <!-- Some default settings -->
15         <persistence-unit-defaults>
16             <!--
17                 Escape all SQL column/table/etc. names, e.g. if your SQL
18                 names are actually keywords (a "USER" table for example)
19               -->
20             <delimited-identifiers/>
21         </persistence-unit-defaults>
22 
23     </persistence-unit-metadata>
24 
25     <entity class="org.jpwh.model.simple.Item" access="FIELD">
26         <attributes>
27             <id name="id">
28                 <generated-value strategy="AUTO"/>
29             </id>
30             <basic name="name"/>
31             <basic name="auctionEnd">
32                 <temporal>TIMESTAMP</temporal>
33             </basic>
34             <transient name="bids"/>
35             <transient name="category"/>
36         </attributes>
37     </entity>
38 
39 </entity-mappings>

 

2.MappingsOverride.xml

 1 <entity-mappings
 2         version="2.1"
 3         xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
 4         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
 6             http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
 7 
 8     <entity class="org.jpwh.model.simple.Item">
 9         <attributes>
10             <!-- Override the SQL column name -->
11             <basic name="name">
12                 <column name="ITEM_NAME"/>
13             </basic>
14         </attributes>
15     </entity>
16 
17 </entity-mappings>

 

3.Queries.xml

 1 <entity-mappings
 2         version="2.1"
 3         xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
 4         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
 6             http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
 7 
 8     <named-query name="findItems">
 9         <query><![CDATA[
10         select i from Item i
11         ]]></query>
12     </named-query>
13 
14     <named-query name="findItemsWithHints">
15         <query>select i from Item i</query>
16         <hint name="org.hibernate.comment" value="My Comment"/>
17         <hint name="org.hibernate.fetchSize" value="50"/>
18         <hint name="org.hibernate.readOnly" value="true"/>
19         <hint name="org.hibernate.timeout" value="60"/>
20     </named-query>
21 
22 </entity-mappings>

 

4.Native.hbm.xml

 1 <?xml version="1.0"?>
 2 <!-- 
 3   Metadata is declared inside a <code>&lt;hibernate-mapping&gt;</code> root element. Attributes such as
 4   <code>package</code> name and <code>default-access</code> apply to all mappings in this file. You may include as many
 5   entity class mappings as you like.
 6   -->
 7 <hibernate-mapping
 8         xmlns="http://www.hibernate.org/xsd/orm/hbm"
 9         package="org.jpwh.model.simple"
10         default-access="field">
11 
12     <!-- An entity class mapping -->
13     <class name="Item">
14         <id name="id">
15             <generator class="native"/>
16         </id>
17         <property name="name"/>
18         <property name="auctionEnd" type="timestamp"/>
19     </class>
20 
21     <!-- Externalized queries -->
22     <query name="findItemsHibernate">select i from Item i</query>
23 
24     <!-- Auxiliary schema DDL -->
25     <database-object>
26         <create>create index ITEM_NAME_IDX on ITEM(NAME)</create>
27         <drop>drop index if exists ITEM_NAME_IDX</drop>
28     </database-object>
29 
30 </hibernate-mapping>

 

三、domain层

1.

 1 package org.jpwh.model.querying;
 2 
 3 import org.jpwh.model.Constants;
 4 
 5 import javax.persistence.*;
 6 import javax.validation.constraints.NotNull;
 7 import java.math.BigDecimal;
 8 
 9 @Entity
10 public class Bid {
11 
12     @Id
13     @GeneratedValue(generator = Constants.ID_GENERATOR)
14     protected Long id;
15 
16     @NotNull
17     @ManyToOne(fetch = FetchType.LAZY)
18     @JoinColumn(foreignKey = @ForeignKey(name = "FK_BID_ITEM_ID"))
19     protected Item item;
20 
21     @ManyToOne(optional = false, fetch = FetchType.LAZY)
22     @JoinColumn(foreignKey = @ForeignKey(name = "FK_BID_BIDDER_ID"))
23     protected User bidder;
24 
25     @NotNull
26     protected BigDecimal amount;
27 
28     public Bid() {
29     }
30 
31     public Bid(Item item, User bidder, BigDecimal amount) {
32         this.item = item;
33         this.amount = amount;
34         this.bidder = bidder;
35     }
36 
37     public Item getItem() {
38         return item;
39     }
40 
41     public void setItem(Item item) {
42         this.item = item;
43     }
44 
45     public User getBidder() {
46         return bidder;
47     }
48 
49     public void setBidder(User bidder) {
50         this.bidder = bidder;
51     }
52 
53     public BigDecimal getAmount() {
54         return amount;
55     }
56 
57     public void setAmount(BigDecimal amount) {
58         this.amount = amount;
59     }
60 }

 

2.

  1 package org.jpwh.model.querying;
  2 
  3 import org.jpwh.model.Constants;
  4 
  5 import javax.persistence.*;
  6 import javax.validation.constraints.NotNull;
  7 import java.math.BigDecimal;
  8 import java.util.Date;
  9 import java.util.HashSet;
 10 import java.util.Set;
 11 
 12 @NamedQueries({
 13     @NamedQuery(
 14         name = "findItemById",
 15         query = "select i from Item i where i.id = :id"
 16     )
 17     ,
 18     @NamedQuery(
 19         name = "findItemByName",
 20         query = "select i from Item i where i.name like :name",
 21         hints = {
 22             @QueryHint(
 23                 name = org.hibernate.annotations.QueryHints.TIMEOUT_JPA,
 24                 value = "60000"),
 25             @QueryHint(
 26                 name = org.hibernate.annotations.QueryHints.COMMENT,
 27                 value = "Custom SQL comment")
 28         }
 29     )
 30 })
 31 @SqlResultSetMappings({
 32     @SqlResultSetMapping(
 33         name = "ItemResult",
 34         entities =
 35         @EntityResult(
 36             entityClass = Item.class,
 37             fields = {
 38                 @FieldResult(name = "id", column = "ID"),
 39                 @FieldResult(name = "name", column = "EXTENDED_NAME"),
 40                 @FieldResult(name = "createdOn", column = "CREATEDON"),
 41                 @FieldResult(name = "auctionEnd", column = "AUCTIONEND"),
 42                 @FieldResult(name = "auctionType", column = "AUCTIONTYPE"),
 43                 @FieldResult(name = "approved", column = "APPROVED"),
 44                 @FieldResult(name = "buyNowPrice", column = "BUYNOWPRICE"),
 45                 @FieldResult(name = "seller", column = "SELLER_ID")
 46             }
 47         )
 48     )
 49 })
 50 @Entity
 51 public class Item {
 52 
 53     @Id
 54     @GeneratedValue(generator = Constants.ID_GENERATOR)
 55     protected Long id;
 56 
 57     @NotNull
 58     protected String name;
 59 
 60     @NotNull
 61     protected Date createdOn = new Date();
 62 
 63     @NotNull
 64     protected Date auctionEnd;
 65 
 66     @NotNull
 67     @Enumerated(EnumType.STRING)
 68     protected AuctionType auctionType = AuctionType.HIGHEST_BID;
 69 
 70     @NotNull
 71     protected boolean approved = true;
 72 
 73     protected BigDecimal buyNowPrice;
 74 
 75     @ManyToOne(optional = false, fetch = FetchType.LAZY)
 76     @JoinColumn(foreignKey = @ForeignKey(name = "FK_ITEM_SELLER_ID"))
 77     protected User seller;
 78 
 79     @ManyToMany(mappedBy = "items")
 80     protected Set<Category> categories = new HashSet<>();
 81 
 82     @OneToMany(mappedBy = "item")
 83     protected Set<Bid> bids = new HashSet<>();
 84 
 85     @ElementCollection
 86     @JoinColumn(foreignKey = @ForeignKey(name = "FK_ITEM_IMAGES_ITEM_ID"))
 87     protected Set<Image> images = new HashSet<>();
 88 
 89     public Item() {
 90     }
 91 
 92     public Item(String name, Date auctionEnd, User seller) {
 93         this.name = name;
 94         this.auctionEnd = auctionEnd;
 95         this.seller = seller;
 96     }
 97 
 98     public Long getId() {
 99         return id;
100     }
101 
102     public String getName() {
103         return name;
104     }
105 
106     public void setName(String name) {
107         this.name = name;
108     }
109 
110     public Date getCreatedOn() {
111         return createdOn;
112     }
113 
114     public Date getAuctionEnd() {
115         return auctionEnd;
116     }
117 
118     public void setAuctionEnd(Date auctionEnd) {
119         this.auctionEnd = auctionEnd;
120     }
121 
122     public AuctionType getAuctionType() {
123         return auctionType;
124     }
125 
126     public void setAuctionType(AuctionType auctionType) {
127         this.auctionType = auctionType;
128     }
129 
130     public boolean isApproved() {
131         return approved;
132     }
133 
134     public void setApproved(boolean approved) {
135         this.approved = approved;
136     }
137 
138     public BigDecimal getBuyNowPrice() {
139         return buyNowPrice;
140     }
141 
142     public void setBuyNowPrice(BigDecimal buyNowPrice) {
143         this.buyNowPrice = buyNowPrice;
144     }
145 
146     public User getSeller() {
147         return seller;
148     }
149 
150     public void setSeller(User seller) {
151         this.seller = seller;
152     }
153 
154     public Set<Category> getCategories() {
155         return categories;
156     }
157 
158     public void setCategories(Set<Category> categories) {
159         this.categories = categories;
160     }
161 
162     public Set<Bid> getBids() {
163         return bids;
164     }
165 
166     public void setBids(Set<Bid> bids) {
167         this.bids = bids;
168     }
169 
170     public Set<Image> getImages() {
171         return images;
172     }
173 
174     public void setImages(Set<Image> images) {
175         this.images = images;
176     }
177     // ...
178 }

 

3.

 1 @org.hibernate.annotations.NamedQueries({
 2     @org.hibernate.annotations.NamedQuery(
 3         name = "findItemsOrderByName",
 4         query = "select i from Item i order by i.name asc"
 5     )
 6     ,
 7     @org.hibernate.annotations.NamedQuery(
 8         name = "findItemBuyNowPriceGreaterThan",
 9         query = "select i from Item i where i.buyNowPrice > :price",
10         timeout = 60, // Seconds!
11         comment = "Custom SQL comment"
12     )
13 })
14 
15 package org.jpwh.model.querying;

 

四、测试文件

1.

 1 package org.jpwh.test.simple;
 2 
 3 import org.jpwh.model.simple.Bid;
 4 import org.jpwh.model.simple.Item;
 5 import org.testng.annotations.Test;
 6 
 7 import javax.validation.ConstraintViolation;
 8 import javax.validation.Validation;
 9 import javax.validation.Validator;
10 import javax.validation.ValidatorFactory;
11 import java.util.Date;
12 import java.util.Locale;
13 import java.util.Set;
14 
15 import static org.testng.Assert.*;
16 
17 public class ModelOperations {
18 
19     @Test
20     public void linkBidAndItem() {
21         Item anItem = new Item();
22         Bid aBid = new Bid();
23 
24         anItem.getBids().add(aBid);
25         aBid.setItem(anItem);
26 
27         assertEquals(anItem.getBids().size(), 1);
28         assertTrue(anItem.getBids().contains(aBid));
29         assertEquals(aBid.getItem(), anItem);
30 
31         // Again with convenience method
32         Bid secondBid = new Bid();
33         anItem.addBid(secondBid);
34 
35         assertEquals(2, anItem.getBids().size());
36         assertTrue(anItem.getBids().contains(secondBid));
37         assertEquals(anItem, secondBid.getItem());
38     }
39 
40     @Test
41     public void validateItem() {
42         ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
43         Validator validator = factory.getValidator();
44 
45         Item item = new Item();
46         item.setName("Some Item");
47         item.setAuctionEnd(new Date());
48 
49         Set<ConstraintViolation<Item>> violations = validator.validate(item);
50 
51         // We have one validation error, auction end date was not in the future!
52         assertEquals(1, violations.size());
53 
54         ConstraintViolation<Item> violation = violations.iterator().next();
55         String failedPropertyName =
56                 violation.getPropertyPath().iterator().next().getName();
57 
58         assertEquals(failedPropertyName, "auctionEnd");
59 
60         if (Locale.getDefault().getLanguage().equals("en"))
61             assertEquals(violation.getMessage(), "must be in the future");
62     }
63 
64 }

 

2.

  1 package org.jpwh.test.simple;
  2 
  3 import org.jpwh.env.JPATest;
  4 import org.jpwh.model.simple.Item;
  5 //import org.jpwh.model.simple.Item_;
  6 import org.testng.annotations.Test;
  7 
  8 import javax.persistence.EntityManager;
  9 import javax.persistence.EntityManagerFactory;
 10 import javax.persistence.criteria.CriteriaBuilder;
 11 import javax.persistence.criteria.CriteriaQuery;
 12 import javax.persistence.criteria.Path;
 13 import javax.persistence.criteria.Root;
 14 import javax.persistence.metamodel.Attribute;
 15 import javax.persistence.metamodel.ManagedType;
 16 import javax.persistence.metamodel.Metamodel;
 17 import javax.persistence.metamodel.SingularAttribute;
 18 import javax.persistence.metamodel.Type;
 19 import javax.transaction.UserTransaction;
 20 import java.util.Date;
 21 import java.util.List;
 22 import java.util.Set;
 23 
 24 import static org.testng.Assert.assertEquals;
 25 import static org.testng.Assert.assertFalse;
 26 
 27 public class AccessJPAMetamodel extends JPATest {
 28 
 29     @Override
 30     public void configurePersistenceUnit() throws Exception {
 31         configurePersistenceUnit("SimpleXMLCompletePU");
 32     }
 33 
 34     @Test
 35     public void accessDynamicMetamodel() throws Exception {
 36         EntityManagerFactory entityManagerFactory = JPA.getEntityManagerFactory();
 37 
 38         Metamodel mm = entityManagerFactory.getMetamodel();
 39 
 40         Set<ManagedType<?>> managedTypes = mm.getManagedTypes();
 41         assertEquals(managedTypes.size(), 1);
 42 
 43         ManagedType itemType = managedTypes.iterator().next();
 44         assertEquals(
 45             itemType.getPersistenceType(),
 46             Type.PersistenceType.ENTITY
 47         );
 48 
 49         SingularAttribute nameAttribute =
 50             itemType.getSingularAttribute("name");
 51         assertEquals(
 52             nameAttribute.getJavaType(),
 53             String.class
 54         );
 55         assertEquals(
 56             nameAttribute.getPersistentAttributeType(),
 57             Attribute.PersistentAttributeType.BASIC
 58         );
 59         assertFalse(
 60             nameAttribute.isOptional() // NOT NULL
 61         );
 62 
 63         SingularAttribute auctionEndAttribute =
 64             itemType.getSingularAttribute("auctionEnd");
 65         assertEquals(
 66             auctionEndAttribute.getJavaType(),
 67             Date.class
 68         );
 69         assertFalse(
 70             auctionEndAttribute.isCollection()
 71         );
 72         assertFalse(
 73             auctionEndAttribute.isAssociation()
 74         );
 75     }
 76 
 77 /*    @Test
 78     public void accessStaticMetamodel() throws Exception {
 79 
 80         SingularAttribute nameAttribute = Item_.name;
 81 
 82         assertEquals(
 83             nameAttribute.getJavaType(),
 84             String.class
 85         );
 86     }*/
 87 
 88     @Test
 89     public void queryStaticMetamodel() throws Exception {
 90         UserTransaction tx = TM.getUserTransaction();
 91         try {
 92             tx.begin();
 93 
 94             EntityManager entityManager = JPA.createEntityManager();
 95 
 96             Item itemOne = new Item();
 97             itemOne.setName("This is some item");
 98             itemOne.setAuctionEnd(new Date(System.currentTimeMillis() + 100000));
 99             entityManager.persist(itemOne);
100 
101             Item itemTwo = new Item();
102             itemTwo.setName("Another item");
103             itemTwo.setAuctionEnd(new Date(System.currentTimeMillis() + 100000));
104 
105             entityManager.persist(itemTwo);
106 
107             tx.commit();
108             entityManager.close();
109 
110             entityManager = JPA.createEntityManager();
111             tx.begin();
112 
113             CriteriaBuilder cb = entityManager.getCriteriaBuilder();
114 
115             // This query is the equivalent of "select i from Item i"
116             CriteriaQuery<Item> query = cb.createQuery(Item.class);
117             Root<Item> fromItem = query.from(Item.class);
118             query.select(fromItem);
119 
120             List<Item> items =
121                 entityManager.createQuery(query)
122                     .getResultList();
123 
124             assertEquals(items.size(), 2);
125 
126             // "where i.name like :pattern"
127             Path<String> namePath = fromItem.get("name");
128             query.where(
129                 cb.like(
130                     namePath, // Has to be a Path<String> for like() operator!
131                     cb.parameter(String.class, "pattern")
132                 )
133             );
134 
135             items =
136                 entityManager.createQuery(query)
137                     .setParameter("pattern", "%some item%") // Wildcards!
138                     .getResultList();
139 
140             assertEquals(items.size(), 1);
141             assertEquals(items.iterator().next().getName(), "This is some item");
142 
143 //            query.where(
144 //                cb.like(
145 //                    fromItem.get(Item_.name), // Static Item_ metamodel!
146 //                    cb.parameter(String.class, "pattern")
147 //                )
148 //            );
149 
150             items =
151                 entityManager.createQuery(query)
152                     .setParameter("pattern", "%some item%") // Wildcard!
153                     .getResultList();
154 
155             assertEquals(items.size(), 1);
156             assertEquals(items.iterator().next().getName(), "This is some item");
157 
158             tx.commit();
159             entityManager.close();
160         } finally {
161             TM.rollback();
162         }
163     }
164 
165 }

 

 

posted @ 2016-04-03 17:07  shamgod  阅读(411)  评论(0编辑  收藏  举报
haha