学习尚硅谷jpa笔记:
所依赖的jar包:
首先在META-INF下创建配置文件,persistence.xml
1 25 6 11 51org.hibernate.ejb.HibernatePersistence 12 13 14com.atguigu.jpa.helloworld.Customer 15com.atguigu.jpa.helloworld.Order 16 17com.atguigu.jpa.helloworld.Department 18com.atguigu.jpa.helloworld.Manager 19 20com.atguigu.jpa.helloworld.Item 21com.atguigu.jpa.helloworld.Category 22 23 31ENABLE_SELECTIVE 32 3334 35 5036 37 38 39 40 41 42 43 44 45 46 47 48 49
下面是使用jpa的基本流程:
1 //1. 创建 EntitymanagerFactory 2 String persistenceUnitName = "jpa-1"; 3 4 Mapproperites = new HashMap (); 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 的 SessionFactory12 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. 关闭 EntityManager32 entityManager.close();33 34 //7. 关闭 EntityManagerFactory35 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 Listemails = 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 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
以下是测试中用到的各个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 @Entity15 public class Category {16 17 private Integer id;18 private String categoryName;19 20 private Set- items = new HashSet<>();21 22 @GeneratedValue23 @Id24 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
- getItems() {43 return items;44 }45 46 public void setItems(Set
- 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 Setorders = 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 getOrders() {120 return orders;121 }122 123 public void setOrders(Set orders) {124 this.orders = orders;125 }126 127 //工具方法. 不需要映射为数据表的一列. 128 @Transient129 public String getInfo(){130 return "lastName: " + lastName + ", email: " + email;131 }132 133 @Override134 public String toString() {135 return "Customer [id=" + id + ", lastName=" + lastName + ", email="136 + email + ", age=" + age + ", createdTime=" + createdTime137 + ", 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 @Entity14 public class Department {15 16 private Integer id;17 private String deptName;18 19 private Manager mgr;20 21 @GeneratedValue22 @Id23 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=true42 @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 @Entity17 public class Item {18 19 private Integer id;20 private String itemName;21 22 private Setcategories = new HashSet<>();23 24 @GeneratedValue25 @Id26 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 @ManyToMany54 public Set getCategories() {55 return categories;56 }57 58 public void setCategories(Set 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 @Entity13 public class Manager {14 15 private Integer id;16 private String mgrName;17 18 private Department dept;19 20 @GeneratedValue21 @Id22 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=true40 @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 @Entity14 public class Order {15 16 private Integer id;17 private String orderName;18 19 private Customer customer;20 21 @GeneratedValue22 @Id23 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异常。
实体的状态:
新建状态: 新创建的对象,尚未拥有持久性主键。
持久化状态:已经拥有持久性主键并和持久化建立了上下文环境
游离状态:拥有持久化主键,但是没有与持久化建立上下文环境
删除状态: 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除。