hykd

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

学习尚硅谷jpa笔记:

 

所依赖的jar包:

首先在META-INF下创建配置文件,persistence.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <persistence version="2.0"
 3     xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
 5     <persistence-unit name="jpa-1" transaction-type="RESOURCE_LOCAL">
 6         <!-- 
 7         配置使用什么 ORM 产品来作为 JPA 的实现 
 8         1. 实际上配置的是  javax.persistence.spi.PersistenceProvider 接口的实现类
 9         2. 若 JPA 项目中只有一个 JPA 的实现产品, 则也可以不配置该节点. 
10         -->
11         <provider>org.hibernate.ejb.HibernatePersistence</provider>
12     
13         <!-- 添加持久化类 -->
14         <class>com.atguigu.jpa.helloworld.Customer</class>
15         <class>com.atguigu.jpa.helloworld.Order</class>
16     
17         <class>com.atguigu.jpa.helloworld.Department</class>
18         <class>com.atguigu.jpa.helloworld.Manager</class>
19     
20         <class>com.atguigu.jpa.helloworld.Item</class>
21         <class>com.atguigu.jpa.helloworld.Category</class>
22         
23         <!-- 
24         配置二级缓存的策略 
25         ALL:所有的实体类都被缓存
26         NONE:所有的实体类都不被缓存. 
27         ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存
28         DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类
29         UNSPECIFIED:默认值,JPA 产品默认值将被使用
30         -->
31         <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
32     
33         <properties>
34             <!-- 连接数据库的基本信息 -->
35             <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
36             <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
37             <property name="javax.persistence.jdbc.user" value="root"/>
38             <property name="javax.persistence.jdbc.password" value="1230"/>
39             
40             <!-- 配置 JPA 实现产品的基本属性. 配置 hibernate 的基本属性 -->
41             <property name="hibernate.format_sql" value="true"/>
42             <property name="hibernate.show_sql" value="true"/>
43             <property name="hibernate.hbm2ddl.auto" value="update"/>
44             
45             <!-- 二级缓存相关 -->
46             <property name="hibernate.cache.use_second_level_cache" value="true"/>
47             <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
48             <property name="hibernate.cache.use_query_cache" value="true"/>
49         </properties>
50     </persistence-unit>
51 </persistence>

下面是使用jpa的基本流程:

 1 //1. 创建 EntitymanagerFactory
 2         String persistenceUnitName = "jpa-1";
 3         
 4         Map<String, Object> properites = new HashMap<String, Object>();
 5         properites.put("hibernate.show_sql", true);
 6         
 7         EntityManagerFactory entityManagerFactory = 
 8                 //Persistence.createEntityManagerFactory(persistenceUnitName);
 9                 Persistence.createEntityManagerFactory(persistenceUnitName, properites);
10                 
11         //2. 创建 EntityManager. 类似于 Hibernate 的 SessionFactory
12         EntityManager entityManager = entityManagerFactory.createEntityManager();
13         
14         //3. 开启事务
15         EntityTransaction transaction = entityManager.getTransaction();
16         transaction.begin();
17         
18         //4. 进行持久化操作
19         Customer customer = new Customer();
20         customer.setAge(12);
21         customer.setEmail("tom@atguigu.com");
22         customer.setLastName("Tom");
23         customer.setBirth(new Date());
24         customer.setCreatedTime(new Date());
25         
26         entityManager.persist(customer);
27         
28         //5. 提交事务
29         transaction.commit();
30         
31         //6. 关闭 EntityManager
32         entityManager.close();
33         
34         //7. 关闭 EntityManagerFactory
35         entityManagerFactory.close();

各种情况下的测试:

  1 package com.atguigu.jpa.test;
  2 
  3 import java.util.Date;
  4 import java.util.List;
  5 
  6 import javax.persistence.EntityManager;
  7 import javax.persistence.EntityManagerFactory;
  8 import javax.persistence.EntityTransaction;
  9 import javax.persistence.Persistence;
 10 import javax.persistence.Query;
 11 
 12 import org.hibernate.ejb.QueryHints;
 13 import org.junit.After;
 14 import org.junit.Before;
 15 import org.junit.Test;
 16 
 17 import com.atguigu.jpa.helloworld.Category;
 18 import com.atguigu.jpa.helloworld.Customer;
 19 import com.atguigu.jpa.helloworld.Department;
 20 import com.atguigu.jpa.helloworld.Item;
 21 import com.atguigu.jpa.helloworld.Manager;
 22 import com.atguigu.jpa.helloworld.Order;
 23 
 24 public class JPATest {
 25 
 26     private EntityManagerFactory entityManagerFactory;
 27     private EntityManager entityManager;
 28     private EntityTransaction transaction;
 29     
 30     @Before
 31     public void init(){
 32         entityManagerFactory = Persistence.createEntityManagerFactory("jpa-1");
 33         entityManager = entityManagerFactory.createEntityManager();
 34         transaction = entityManager.getTransaction();
 35         transaction.begin();
 36     }
 37     
 38     @After
 39     public void destroy(){
 40         transaction.commit();
 41         entityManager.close();
 42         entityManagerFactory.close();
 43     }
 44     
 45     //可以使用 JPQL 完成 UPDATE 和 DELETE 操作. 
 46     @Test
 47     public void testExecuteUpdate(){
 48         String jpql = "UPDATE Customer c SET c.lastName = ? WHERE c.id = ?";
 49         Query query = entityManager.createQuery(jpql).setParameter(1, "YYY").setParameter(2, 12);
 50         
 51         query.executeUpdate();
 52     }
 53 
 54     //使用 jpql 内建的函数
 55     @Test
 56     public void testJpqlFunction(){
 57         String jpql = "SELECT lower(c.email) FROM Customer c";
 58         
 59         List<String> emails = entityManager.createQuery(jpql).getResultList();
 60         System.out.println(emails);
 61     }
 62     
 63     @Test
 64     public void testSubQuery(){
 65         //查询所有 Customer 的 lastName 为 YY 的 Order
 66         String jpql = "SELECT o FROM Order o "
 67                 + "WHERE o.customer = (SELECT c FROM Customer c WHERE c.lastName = ?)";
 68         
 69         Query query = entityManager.createQuery(jpql).setParameter(1, "YY");
 70         List<Order> orders = query.getResultList();
 71         System.out.println(orders.size());
 72     }
 73     
 74     /**
 75      * JPQL 的关联查询同 HQL 的关联查询. 
 76      */
 77     @Test
 78     public void testLeftOuterJoinFetch(){
 79         String jpql = "FROM Customer c LEFT OUTER JOIN FETCH c.orders WHERE c.id = ?";
 80         
 81         Customer customer = 
 82                 (Customer) entityManager.createQuery(jpql).setParameter(1, 12).getSingleResult();
 83         System.out.println(customer.getLastName());
 84         System.out.println(customer.getOrders().size());
 85         
 86 //        List<Object[]> result = entityManager.createQuery(jpql).setParameter(1, 12).getResultList();
 87 //        System.out.println(result);
 88     }
 89     
 90     //查询 order 数量大于 2 的那些 Customer
 91     @Test
 92     public void testGroupBy(){
 93         String jpql = "SELECT o.customer FROM Order o "
 94                 + "GROUP BY o.customer "
 95                 + "HAVING count(o.id) >= 2";
 96         List<Customer> customers = entityManager.createQuery(jpql).getResultList();
 97         
 98         System.out.println(customers);
 99     }
100     
101     @Test
102     public void testOrderBy(){
103         String jpql = "FROM Customer c WHERE c.age > ? ORDER BY c.age DESC";
104         Query query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);
105         
106         //占位符的索引是从 1 开始
107         query.setParameter(1, 1);
108         List<Customer> customers = query.getResultList();
109         System.out.println(customers.size());
110     }
111     
112     //使用 hibernate 的查询缓存. 
113     @Test
114     public void testQueryCache(){
115         String jpql = "FROM Customer c WHERE c.age > ?";
116         Query query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);
117         
118         //占位符的索引是从 1 开始
119         query.setParameter(1, 1);
120         List<Customer> customers = query.getResultList();
121         System.out.println(customers.size());
122         
123         query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);
124         
125         //占位符的索引是从 1 开始
126         query.setParameter(1, 1);
127         customers = query.getResultList();
128         System.out.println(customers.size());
129     }
130     
131     //createNativeQuery 适用于本地 SQL
132     @Test
133     public void testNativeQuery(){
134         String sql = "SELECT age FROM jpa_cutomers WHERE id = ?";
135         Query query = entityManager.createNativeQuery(sql).setParameter(1, 3);
136         
137         Object result = query.getSingleResult();
138         System.out.println(result);
139     }
140     
141     //createNamedQuery 适用于在实体类前使用 @NamedQuery 标记的查询语句
142     @Test
143     public void testNamedQuery(){
144         Query query = entityManager.createNamedQuery("testNamedQuery").setParameter(1, 3);
145         Customer customer = (Customer) query.getSingleResult();
146         
147         System.out.println(customer);
148     }
149     
150     //默认情况下, 若只查询部分属性, 则将返回 Object[] 类型的结果. 或者 Object[] 类型的 List.
151     //也可以在实体类中创建对应的构造器, 然后再 JPQL 语句中利用对应的构造器返回实体类的对象.
152     @Test
153     public void testPartlyProperties(){
154         String jpql = "SELECT new Customer(c.lastName, c.age) FROM Customer c WHERE c.id > ?";
155         List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();
156         
157         System.out.println(result);
158     }
159     
160     @Test
161     public void testHelloJPQL(){
162         String jpql = "FROM Customer c WHERE c.age > ?";
163         Query query = entityManager.createQuery(jpql);
164         
165         //占位符的索引是从 1 开始
166         query.setParameter(1, 1);
167         List<Customer> customers = query.getResultList();
168         System.out.println(customers.size());
169     }
170     
171     @Test
172     public void testSecondLevelCache(){
173         Customer customer1 = entityManager.find(Customer.class, 1);
174         
175         transaction.commit();
176         entityManager.close();
177         
178         entityManager = entityManagerFactory.createEntityManager();
179         transaction = entityManager.getTransaction();
180         transaction.begin();
181         
182         Customer customer2 = entityManager.find(Customer.class, 1);
183     }
184     
185     //对于关联的集合对象, 默认使用懒加载的策略.
186     //使用维护关联关系的一方获取, 还是使用不维护关联关系的一方获取, SQL 语句相同. 
187     @Test
188     public void testManyToManyFind(){
189 //        Item item = entityManager.find(Item.class, 5);
190 //        System.out.println(item.getItemName());
191 //        
192 //        System.out.println(item.getCategories().size());
193         
194         Category category = entityManager.find(Category.class, 3);
195         System.out.println(category.getCategoryName());
196         System.out.println(category.getItems().size());
197     }
198     
199     //多对所的保存
200     @Test
201     public void testManyToManyPersist(){
202         Item i1 = new Item();
203         i1.setItemName("i-1");
204     
205         Item i2 = new Item();
206         i2.setItemName("i-2");
207         
208         Category c1 = new Category();
209         c1.setCategoryName("C-1");
210         
211         Category c2 = new Category();
212         c2.setCategoryName("C-2");
213         
214         //设置关联关系
215         i1.getCategories().add(c1);
216         i1.getCategories().add(c2);
217         
218         i2.getCategories().add(c1);
219         i2.getCategories().add(c2);
220         
221         c1.getItems().add(i1);
222         c1.getItems().add(i2);
223         
224         c2.getItems().add(i1);
225         c2.getItems().add(i2);
226         
227         //执行保存
228         entityManager.persist(i1);
229         entityManager.persist(i2);
230         entityManager.persist(c1);
231         entityManager.persist(c2);
232     }
233     
234     //1. 默认情况下, 若获取不维护关联关系的一方, 则也会通过左外连接获取其关联的对象. 
235     //可以通过 @OneToOne 的 fetch 属性来修改加载策略. 但依然会再发送 SQL 语句来初始化其关联的对象
236     //这说明在不维护关联关系的一方, 不建议修改 fetch 属性. 
237     @Test
238     public void testOneToOneFind2(){
239         Manager mgr = entityManager.find(Manager.class, 1);
240         System.out.println(mgr.getMgrName());
241         
242         System.out.println(mgr.getDept().getClass().getName());
243     }
244     
245     //1.默认情况下, 若获取维护关联关系的一方, 则会通过左外连接获取其关联的对象. 
246     //但可以通过 @OntToOne 的 fetch 属性来修改加载策略.
247     @Test
248     public void testOneToOneFind(){
249         Department dept = entityManager.find(Department.class, 1);
250         System.out.println(dept.getDeptName());
251         System.out.println(dept.getMgr().getClass().getName());
252     }
253     
254     //双向 1-1 的关联关系, 建议先保存不维护关联关系的一方, 即没有外键的一方, 这样不会多出 UPDATE 语句.
255     @Test
256     public void testOneToOnePersistence(){
257         Manager mgr = new Manager();
258         mgr.setMgrName("M-BB");
259         
260         Department dept = new Department();
261         dept.setDeptName("D-BB");
262         
263         //设置关联关系
264         mgr.setDept(dept);
265         dept.setMgr(mgr);
266         
267         //执行保存操作
268         entityManager.persist(mgr);
269         entityManager.persist(dept);
270     }
271     
272     @Test
273     public void testUpdate(){
274         Customer customer = entityManager.find(Customer.class, 10);
275         
276         customer.getOrders().iterator().next().setOrderName("O-XXX-10");
277     }
278     
279     //默认情况下, 若删除 1 的一端, 则会先把关联的 n 的一端的外键置空, 然后进行删除. 
280     //可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. 
281     @Test
282     public void testOneToManyRemove(){
283         Customer customer = entityManager.find(Customer.class, 8);
284         entityManager.remove(customer);
285     }
286     
287     //默认对关联的多的一方使用懒加载的加载策略. 
288     //可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
289     @Test
290     public void testOneToManyFind(){
291         Customer customer = entityManager.find(Customer.class, 9);
292         System.out.println(customer.getLastName());
293         
294         System.out.println(customer.getOrders().size());
295     }
296     
297     //若是双向 1-n 的关联关系, 执行保存时
298     //若先保存 n 的一端, 再保存 1 的一端, 默认情况下, 会多出 n 条 UPDATE 语句.
299     //若先保存 1 的一端, 则会多出 n 条 UPDATE 语句
300     //在进行双向 1-n 关联关系时, 建议使用 n 的一方来维护关联关系, 而 1 的一方不维护关联系, 这样会有效的减少 SQL 语句. 
301     //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了. 
302     
303     //单向 1-n 关联关系执行保存时, 一定会多出 UPDATE 语句.
304     //因为 n 的一端在插入时不会同时插入外键列. 
305     @Test
306     public void testOneToManyPersist(){
307         Customer customer = new Customer();
308         customer.setAge(18);
309         customer.setBirth(new Date());
310         customer.setCreatedTime(new Date());
311         customer.setEmail("mm@163.com");
312         customer.setLastName("MM");
313         
314         Order order1 = new Order();
315         order1.setOrderName("O-MM-1");
316         
317         Order order2 = new Order();
318         order2.setOrderName("O-MM-2");
319         
320         //建立关联关系
321         customer.getOrders().add(order1);
322         customer.getOrders().add(order2);
323         
324         order1.setCustomer(customer);
325         order2.setCustomer(customer);
326         
327         //执行保存操作
328         entityManager.persist(customer);
329 
330         entityManager.persist(order1);
331         entityManager.persist(order2);
332     }
333     
334     /*
335     @Test
336     public void testManyToOneUpdate(){
337         Order order = entityManager.find(Order.class, 2);
338         order.getCustomer().setLastName("FFF");
339     }
340     
341     //不能直接删除 1 的一端, 因为有外键约束. 
342     @Test
343     public void testManyToOneRemove(){
344 //        Order order = entityManager.find(Order.class, 1);
345 //        entityManager.remove(order);
346         
347         Customer customer = entityManager.find(Customer.class, 7);
348         entityManager.remove(customer);
349     }
350     
351     //默认情况下, 使用左外连接的方式来获取 n 的一端的对象和其关联的 1 的一端的对象. 
352     //可使用 @ManyToOne 的 fetch 属性来修改默认的关联属性的加载策略
353     @Test
354     public void testManyToOneFind(){
355         Order order = entityManager.find(Order.class, 1);
356         System.out.println(order.getOrderName());
357         
358         System.out.println(order.getCustomer().getLastName());
359     }
360     */
361     
362     /**
363      * 保存多对一时, 建议先保存 1 的一端, 后保存 n 的一端, 这样不会多出额外的 UPDATE 语句.
364      */
365     /*
366     @Test
367     public void testManyToOnePersist(){
368         Customer customer = new Customer();
369         customer.setAge(18);
370         customer.setBirth(new Date());
371         customer.setCreatedTime(new Date());
372         customer.setEmail("gg@163.com");
373         customer.setLastName("GG");
374         
375         Order order1 = new Order();
376         order1.setOrderName("G-GG-1");
377         
378         Order order2 = new Order();
379         order2.setOrderName("G-GG-2");
380         
381         //设置关联关系
382         order1.setCustomer(customer);
383         order2.setCustomer(customer);
384         
385         //执行保存操作
386         entityManager.persist(order1);
387         entityManager.persist(order2);
388         
389         entityManager.persist(customer);
390     }
391     */
392     
393     /**
394      * 同 hibernate 中 Session 的 refresh 方法. 会重新执行查询语句
395      */
396     @Test
397     public void testRefresh(){
398         Customer customer = entityManager.find(Customer.class, 1);
399         customer = entityManager.find(Customer.class, 1);
400         
401         entityManager.refresh(customer);
402     }
403     
404     /**
405      * 同 hibernate 中 Session 的 flush 方法. 效果相当于提前提交事务
406      */
407     @Test
408     public void testFlush(){
409         Customer customer = entityManager.find(Customer.class, 1);
410         System.out.println(customer);
411         
412         customer.setLastName("AA");
413         
414         entityManager.flush();
415     }
416     
417     //若传入的是一个游离对象, 即传入的对象有 OID. 
418     //1. 若在 EntityManager 缓存中有对应的对象
419     //2. JPA 会把游离对象的属性复制到查询到EntityManager 缓存中的对象中.
420     //3. EntityManager 缓存中的对象执行 UPDATE. 
421     @Test
422     public void testMerge4(){
423         Customer customer = new Customer();
424         customer.setAge(18);
425         customer.setBirth(new Date());
426         customer.setCreatedTime(new Date());
427         customer.setEmail("dd@163.com");
428         customer.setLastName("DD");
429         
430         customer.setId(4);
431         Customer customer2 = entityManager.find(Customer.class, 4);
432         
433         entityManager.merge(customer);
434         
435         System.out.println(customer == customer2); //false
436     }
437     
438     //若传入的是一个游离对象, 即传入的对象有 OID. 
439     //1. 若在 EntityManager 缓存中没有该对象
440     //2. 若在数据库中有对应的记录
441     //3. JPA 会查询对应的记录, 然后返回该记录对一个的对象, 再然后会把游离对象的属性复制到查询到的对象中.
442     //4. 对查询到的对象执行 update 操作. 
443     @Test
444     public void testMerge3(){
445         Customer customer = new Customer();
446         customer.setAge(18);
447         customer.setBirth(new Date());
448         customer.setCreatedTime(new Date());
449         customer.setEmail("ee@163.com");
450         customer.setLastName("EE");
451         
452         customer.setId(4);
453         
454         Customer customer2 = entityManager.merge(customer);
455         
456         System.out.println(customer == customer2); //false
457     }
458     
459     //若传入的是一个游离对象, 即传入的对象有 OID. 
460     //1. 若在 EntityManager 缓存中没有该对象
461     //2. 若在数据库中也没有对应的记录
462     //3. JPA 会创建一个新的对象, 然后把当前游离对象的属性复制到新创建的对象中
463     //4. 对新创建的对象执行 insert 操作. 
464     @Test
465     public void testMerge2(){
466         Customer customer = new Customer();
467         customer.setAge(18);
468         customer.setBirth(new Date());
469         customer.setCreatedTime(new Date());
470         customer.setEmail("dd@163.com");
471         customer.setLastName("DD");
472         
473         customer.setId(100);
474         
475         Customer customer2 = entityManager.merge(customer);
476         
477         System.out.println("customer#id:" + customer.getId());
478         System.out.println("customer2#id:" + customer2.getId());
479     }
480     
481     /**
482      * 总的来说: 类似于 hibernate Session 的 saveOrUpdate 方法.
483      */
484     //1. 若传入的是一个临时对象
485     //会创建一个新的对象, 把临时对象的属性复制到新的对象中, 然后对新的对象执行持久化操作. 所以
486     //新的对象中有 id, 但以前的临时对象中没有 id. 
487     @Test
488     public void testMerge1(){
489         Customer customer = new Customer();
490         customer.setAge(18);
491         customer.setBirth(new Date());
492         customer.setCreatedTime(new Date());
493         customer.setEmail("cc@163.com");
494         customer.setLastName("CC");
495         
496         Customer customer2 = entityManager.merge(customer);
497         
498         System.out.println("customer#id:" + customer.getId());
499         System.out.println("customer2#id:" + customer2.getId());
500     }
501     
502     //类似于 hibernate 中 Session 的 delete 方法. 把对象对应的记录从数据库中移除
503     //但注意: 该方法只能移除 持久化 对象. 而 hibernate 的 delete 方法实际上还可以通过游离对象移除数据库记录.
504     @Test
505     public void testRemove(){
506 //        Customer customer = new Customer();
507 //        customer.setId(2);
508         
509         Customer customer = entityManager.find(Customer.class, 2);
510         entityManager.remove(customer);
511     }
512     
513     //类似于 hibernate 的 save 方法. 使对象由临时状态变为持久化状态. 
514     //和 hibernate 的 save 方法的不同之处: 若对象有 id, 则不能执行 insert 操作, 而会抛出异常. 
515     @Test
516     public void testPersistence(){
517         Customer customer = new Customer();
518         customer.setAge(15);
519         customer.setBirth(new Date());
520         customer.setCreatedTime(new Date());
521         customer.setEmail("bb@163.com");
522         customer.setLastName("BB");
523         customer.setId(100);
524         
525         entityManager.persist(customer);
526         System.out.println(customer.getId());
527     }
528     
529     //类似于 hibernate 中 Session 的 load 方法,注意懒加载产生的问题
530     @Test
531     public void testGetReference(){
532         Customer customer = entityManager.getReference(Customer.class, 1);
533         System.out.println(customer.getClass().getName());
534         
535         System.out.println("-------------------------------------");
536 //        transaction.commit();
537 //        entityManager.close();
538         
539         System.out.println(customer);
540     }
541     
542     //类似于 hibernate 中 Session 的 get 方法. 
543     @Test
544     public void testFind() {
545         Customer customer = entityManager.find(Customer.class, 1);
546         System.out.println("-------------------------------------");
547         
548         System.out.println(customer);
549     }
550 
551 }

以下是测试中用到的各个model:

Category:

 1 package com.atguigu.jpa.helloworld;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 import javax.persistence.Column;
 7 import javax.persistence.Entity;
 8 import javax.persistence.GeneratedValue;
 9 import javax.persistence.Id;
10 import javax.persistence.ManyToMany;
11 import javax.persistence.Table;
12 
13 @Table(name="JPA_CATEGORIES")
14 @Entity
15 public class Category {
16 
17     private Integer id;
18     private String categoryName;
19     
20     private Set<Item> items = new HashSet<>();
21 
22     @GeneratedValue
23     @Id
24     public Integer getId() {
25         return id;
26     }
27 
28     public void setId(Integer id) {
29         this.id = id;
30     }
31 
32     @Column(name="CATEGORY_NAME")
33     public String getCategoryName() {
34         return categoryName;
35     }
36 
37     public void setCategoryName(String categoryName) {
38         this.categoryName = categoryName;
39     }
40 
41     @ManyToMany(mappedBy="categories")
42     public Set<Item> getItems() {
43         return items;
44     }
45 
46     public void setItems(Set<Item> items) {
47         this.items = items;
48     }
49 }

Customer:

  1 package com.atguigu.jpa.helloworld;
  2 
  3 import java.util.Date;
  4 import java.util.HashSet;
  5 import java.util.Set;
  6 
  7 import javax.persistence.Cacheable;
  8 import javax.persistence.CascadeType;
  9 import javax.persistence.Column;
 10 import javax.persistence.Entity;
 11 import javax.persistence.FetchType;
 12 import javax.persistence.GeneratedValue;
 13 import javax.persistence.GenerationType;
 14 import javax.persistence.Id;
 15 import javax.persistence.NamedQuery;
 16 import javax.persistence.OneToMany;
 17 import javax.persistence.Table;
 18 import javax.persistence.Temporal;
 19 import javax.persistence.TemporalType;
 20 import javax.persistence.Transient;
 21  
 22 @NamedQuery(name="testNamedQuery", query="FROM Customer c WHERE c.id = ?")
 23 @Cacheable(true)
 24 @Table(name="JPA_CUTOMERS")
 25 @Entity
 26 public class Customer {
 27 
 28     private Integer id;
 29     private String lastName;
 30 
 31     private String email;
 32     private int age;
 33     
 34     private Date createdTime;
 35     private Date birth;
 36     
 37     public Customer() {
 38         // TODO Auto-generated constructor stub
 39     }
 40     
 41     public Customer(String lastName, int age) {
 42         super();
 43         this.lastName = lastName;
 44         this.age = age;
 45     }
 46 
 47 
 48 
 49     private Set<Order> orders = new HashSet<>();
 50 
 51 //    @TableGenerator(name="ID_GENERATOR",
 52 //            table="jpa_id_generators",
 53 //            pkColumnName="PK_NAME",
 54 //            pkColumnValue="CUSTOMER_ID",
 55 //            valueColumnName="PK_VALUE",
 56 //            allocationSize=100)
 57 //    @GeneratedValue(strategy=GenerationType.TABLE,generator="ID_GENERATOR")
 58     @GeneratedValue(strategy=GenerationType.AUTO)
 59     @Id
 60     public Integer getId() {
 61         return id;
 62     }
 63 
 64     public void setId(Integer id) {
 65         this.id = id;
 66     }
 67 
 68     @Column(name="LAST_NAME",length=50,nullable=false)
 69     public String getLastName() {
 70         return lastName;
 71     }
 72 
 73     public void setLastName(String lastName) {
 74         this.lastName = lastName;
 75     }
 76 
 77     public String getEmail() {
 78         return email;
 79     }
 80 
 81     public void setEmail(String email) {
 82         this.email = email;
 83     }
 84 
 85     public int getAge() {
 86         return age;
 87     }
 88 
 89     public void setAge(int age) {
 90         this.age = age;
 91     }
 92     
 93     @Temporal(TemporalType.TIMESTAMP)
 94     public Date getCreatedTime() {
 95         return createdTime;
 96     }
 97 
 98     public void setCreatedTime(Date createdTime) {
 99         this.createdTime = createdTime;
100     }
101 
102     @Temporal(TemporalType.DATE)
103     public Date getBirth() {
104         return birth;
105     }
106 
107     public void setBirth(Date birth) {
108         this.birth = birth;
109     }
110     
111     //映射单向 1-n 的关联关系
112     //使用 @OneToMany 来映射 1-n 的关联关系
113     //使用 @JoinColumn 来映射外键列的名称
114     //可以使用 @OneToMany 的 fetch 属性来修改默认的加载策略
115     //可以通过 @OneToMany 的 cascade 属性来修改默认的删除策略. 
116     //注意: 若在 1 的一端的 @OneToMany 中使用 mappedBy 属性, 则 @OneToMany 端就不能再使用 @JoinColumn 属性了. 
117 //    @JoinColumn(name="CUSTOMER_ID")
118     @OneToMany(fetch=FetchType.LAZY,cascade={CascadeType.REMOVE},mappedBy="customer")
119     public Set<Order> getOrders() {
120         return orders;
121     }
122 
123     public void setOrders(Set<Order> orders) {
124         this.orders = orders;
125     }
126 
127     //工具方法. 不需要映射为数据表的一列. 
128     @Transient
129     public String getInfo(){
130         return "lastName: " + lastName + ", email: " + email;
131     }
132 
133     @Override
134     public String toString() {
135         return "Customer [id=" + id + ", lastName=" + lastName + ", email="
136                 + email + ", age=" + age + ", createdTime=" + createdTime
137                 + ", birth=" + birth + "]";
138     }
139 
140 }

Department:

 1 package com.atguigu.jpa.helloworld;
 2 
 3 import javax.persistence.Column;
 4 import javax.persistence.Entity;
 5 import javax.persistence.FetchType;
 6 import javax.persistence.GeneratedValue;
 7 import javax.persistence.Id;
 8 import javax.persistence.JoinColumn;
 9 import javax.persistence.OneToOne;
10 import javax.persistence.Table;
11 
12 @Table(name="JPA_DEPARTMENTS")
13 @Entity
14 public class Department {
15 
16     private Integer id;
17     private String deptName;
18     
19     private Manager mgr;
20 
21     @GeneratedValue
22     @Id
23     public Integer getId() {
24         return id;
25     }
26 
27     public void setId(Integer id) {
28         this.id = id;
29     }
30 
31     @Column(name="DEPT_NAME")
32     public String getDeptName() {
33         return deptName;
34     }
35 
36     public void setDeptName(String deptName) {
37         this.deptName = deptName;
38     }
39 
40     //使用 @OneToOne 来映射 1-1 关联关系。
41     //若需要在当前数据表中添加主键则需要使用 @JoinColumn 来进行映射. 注意, 1-1 关联关系, 所以需要添加 unique=true
42     @JoinColumn(name="MGR_ID", unique=true)
43     @OneToOne(fetch=FetchType.LAZY)
44     public Manager getMgr() {
45         return mgr;
46     }
47 
48     public void setMgr(Manager mgr) {
49         this.mgr = mgr;
50     }
51 }

Item:

 1 package com.atguigu.jpa.helloworld;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 import javax.persistence.Column;
 7 import javax.persistence.Entity;
 8 import javax.persistence.GeneratedValue;
 9 import javax.persistence.Id;
10 import javax.persistence.JoinColumn;
11 import javax.persistence.JoinTable;
12 import javax.persistence.ManyToMany;
13 import javax.persistence.Table;
14 
15 @Table(name="JPA_ITEMS")
16 @Entity
17 public class Item {
18 
19     private Integer id;
20     private String itemName;
21     
22     private Set<Category> categories = new HashSet<>();
23 
24     @GeneratedValue
25     @Id
26     public Integer getId() {
27         return id;
28     }
29 
30     public void setId(Integer id) {
31         this.id = id;
32     }
33 
34     @Column(name="ITEM_NAME")
35     public String getItemName() {
36         return itemName;
37     }
38 
39     public void setItemName(String itemName) {
40         this.itemName = itemName;
41     }
42 
43     //使用 @ManyToMany 注解来映射多对多关联关系
44     //使用 @JoinTable 来映射中间表
45     //1. name 指向中间表的名字
46     //2. joinColumns 映射当前类所在的表在中间表中的外键
47     //2.1 name 指定外键列的列名
48     //2.2 referencedColumnName 指定外键列关联当前表的哪一列
49     //3. inverseJoinColumns 映射关联的类所在中间表的外键
50     @JoinTable(name="ITEM_CATEGORY",
51             joinColumns={@JoinColumn(name="ITEM_ID", referencedColumnName="ID")},
52             inverseJoinColumns={@JoinColumn(name="CATEGORY_ID", referencedColumnName="ID")})
53     @ManyToMany
54     public Set<Category> getCategories() {
55         return categories;
56     }
57 
58     public void setCategories(Set<Category> categories) {
59         this.categories = categories;
60     }
61 }

Manager:

 1 package com.atguigu.jpa.helloworld;
 2 
 3 import javax.persistence.Column;
 4 import javax.persistence.Entity;
 5 import javax.persistence.FetchType;
 6 import javax.persistence.GeneratedValue;
 7 import javax.persistence.Id;
 8 import javax.persistence.OneToOne;
 9 import javax.persistence.Table;
10 
11 @Table(name="JPA_MANAGERS")
12 @Entity
13 public class Manager {
14 
15     private Integer id;
16     private String mgrName;
17     
18     private Department dept;
19 
20     @GeneratedValue
21     @Id
22     public Integer getId() {
23         return id;
24     }
25 
26     public void setId(Integer id) {
27         this.id = id;
28     }
29 
30     @Column(name="MGR_NAME")
31     public String getMgrName() {
32         return mgrName;
33     }
34 
35     public void setMgrName(String mgrName) {
36         this.mgrName = mgrName;
37     }
38 
39     //对于不维护关联关系, 没有外键的一方, 使用 @OneToOne 来进行映射, 建议设置 mappedBy=true
40     @OneToOne(mappedBy="mgr")
41     public Department getDept() {
42         return dept;
43     }
44 
45     public void setDept(Department dept) {
46         this.dept = dept;
47     }
48 }

Order:

 1 package com.atguigu.jpa.helloworld;
 2 
 3 import javax.persistence.Column;
 4 import javax.persistence.Entity;
 5 import javax.persistence.FetchType;
 6 import javax.persistence.GeneratedValue;
 7 import javax.persistence.Id;
 8 import javax.persistence.JoinColumn;
 9 import javax.persistence.ManyToOne;
10 import javax.persistence.Table;
11 
12 @Table(name="JPA_ORDERS")
13 @Entity
14 public class Order {
15 
16     private Integer id;
17     private String orderName;
18 
19     private Customer customer;
20 
21     @GeneratedValue
22     @Id
23     public Integer getId() {
24         return id;
25     }
26 
27     public void setId(Integer id) {
28         this.id = id;
29     }
30 
31     @Column(name="ORDER_NAME")
32     public String getOrderName() {
33         return orderName;
34     }
35 
36     public void setOrderName(String orderName) {
37         this.orderName = orderName;
38     }
39 
40     //映射单向 n-1 的关联关系
41     //使用 @ManyToOne 来映射多对一的关联关系
42     //使用 @JoinColumn 来映射外键. 
43     //可使用 @ManyToOne 的 fetch 属性来修改默认的关联属性的加载策略
44     @JoinColumn(name="CUSTOMER_ID")
45     @ManyToOne(fetch=FetchType.LAZY)
46     public Customer getCustomer() {
47         return customer;
48     }
49 
50     public void setCustomer(Customer customer) {
51         this.customer = customer;
52     }
53 
54 }

 

补充:

JPA 基本注解:

@Entity @Transient @Temporal @Table  @GeneratedValue @Column @Basic

用 table 来生成主键:

JPA API:

EntityManager#find

EntityManager#getReference

EntityManager#persistence

EntityManager#remove

EntityManager#merge

EntityManager#其他方法

 

EntityManagerFactory该接口约定了如下4个方法:

createEntityManager():用于创建实体管理器对象实例。

createEntityManager(Map map):用于创建实体管理器对象实例的重载方法,Map 参数用于提供 EntityManager 的属性。 isOpen():检查 EntityManagerFactory 是否处于打开状态。实体管理器工厂创建后一直处于打开状态,除非调用close()方法将其关闭。

close():关闭 EntityManagerFactory 。 EntityManagerFactory 关闭后将释放所有资源,

isOpen()方法测试将返回 false,其它方法将不能调用,否则将导致IllegalStateException异常。

 

实体的状态:

新建状态: 新创建的对象,尚未拥有持久性主键。

持久化状态:已经拥有持久性主键并和持久化建立了上下文环境

游离状态:拥有持久化主键,但是没有与持久化建立上下文环境

删除状态: 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除。

 

 

posted on 2016-10-06 22:36  hykd  阅读(650)  评论(0编辑  收藏  举报