标签:
学习尚硅谷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异常。
实体的状态:
新建状态: 新创建的对象,尚未拥有持久性主键。
持久化状态:已经拥有持久性主键并和持久化建立了上下文环境
游离状态:拥有持久化主键,但是没有与持久化建立上下文环境
删除状态: 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除。
标签:
原文地址:http://www.cnblogs.com/yzwhykd/p/5935121.html