本章节将介绍 JPA 的增删改查基础功能。
JPA 通过加载 META-INF/persistence.xml 文件中配置的 <persistence-unit> 来创建 EntityManagerFactory 对象。
EntityManagerFactory 相当于一个连接池对象,用来创建 EntityManager。
EntityManagerFactory 是线程安全的,多线程可以共用同一个 EntityManagerFactory。
注意:创建 EntityManagerFactory 对象需要消耗较多的资源,所以通常一个项目只需要创建一个 EntityManagerFactory 对象。
EntityManager 对象相当于一个连接对象,该对象是线程不安全。
因此,每次对数据库的访问都应该创建一个新的 EntityManager 对象,不能共用。
获取 EntityManager 对象的工具类,代码如下:
public class JPAUtil { private static EntityManagerFactory emf; private JPAUtil() {} static { // 加载 META-INF/persistence.xml 文件中的 <persistence-util> 中的配置 // 信息创建 EntityManagerFactory 对象 emf = Persistence.createEntityManagerFactory("myPersistence"); } /** * 使用 EntityManagerFactory 创建 EntityManager 对象 */ public static EntityManager getEntityManager() { return emf.createEntityManager(); } }
在开始介绍 CRUD 操作之前,我们先看看实体 User 的代码,如下:
@Entity @Table public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column private String name; @Column private Integer age; //...忽略getter和setter... @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
上面代码中,定义了一个实体 User,且该实体映射到 user 数据表。下面将在该表中进行 CRUD 操作:
在 JAP 中使用 void persist(java.lang.Object entity) 方法实现实体持久化。
如果实体已经存在,则在调用持久操作时可能会抛出 EntityExistsException;或者在刷新或提交时可能会抛出 EntityExistsException 或另一个 PersistenceException。
如果实例不是实体,则抛出 IllegalArgumentException 异常。
如果在 PersistenceContextType.TRANSACTION 类型的容器管理实体管理器上调用并且没有事务,则抛出 TransactionRequiredException 异常。
实例代码:
public class OpenJpaAdd { /** 持久化单元名称 */ private static final String NAME = "openJPA"; public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory(NAME); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // 开始事务 // 新增用户信息 User user = new User(); user.setName("Bill-" + DateUtils.getDate()); user.setAge(32); em.persist(user); em.getTransaction().commit(); // 提交事务 em.close(); emf.close(); System.out.println("finished."); } }
在 JPA 中,使用 <T> T merge(T entity) 方法实现实体修改。如果该方法执行成功,则返回新的实体对象(即修改后的实体对象)。
如果实例不是实体或者是已删除的实体,则抛出 IllegalArgumentException 异常。
如果在 PersistenceContextType.TRANSACTION 类型的容器管理实体管理器上调用并且没有事务,则抛出 TransactionRequiredException 异常。
实例代码:
public class OpenJpaUpdate { /** 持久化单元名称 */ private static final String NAME = "openJPA"; public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory(NAME); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); // 开启事务 // 查询ID为1的用户 User oldUser = em.find(User.class, 1L); oldUser.setName(oldUser.getName() + "_update"); // 修改用户信息 User newUser = em.merge(oldUser); System.out.println(newUser); em.getTransaction().commit(); // 提交事务 em.close(); factory.close(); System.out.println("finished."); } }
在 JPA 中,使用 void remove(java.lang.Object entity) 方法删除实体。
如果实例不是实体或者是游离的实体,则抛出 IllegalArgumentException 异常。
如果在 PersistenceContextType.TRANSACTION 类型的容器管理实体管理器上调用并且没有事务,则抛出 TransactionRequiredException 异常。
实例代码:
public class OpenJpaDelete { /** 持久化单元名称 */ private static final String NAME = "openJPA"; public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory(NAME); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // 开始事务 // 查询ID为1的用户信息 User user = em.find(User.class, 1L); if(null != user) { em.remove(user); // 删除用户 } em.getTransaction().commit(); // 提交事务 em.close(); emf.close(); System.out.println("finished."); } }
在 JPA 中,可以使用 <T> T find(java.lang.Class<T> entityClass, java.lang.Object primaryKey) 方法按主键查找实体。如果实体实例包含在持久性上下文中,则从那里返回。其中:
entityClass:查询实体的 Class 类型
primaryKey:带查询实体的主键
如果第一个参数不表示实体类型或第二个参数不是该实体主键的有效类型或为 null,则抛出 IllegalArgumentException 异常。
实例代码:
public class OpenJpaSelect { /** 持久化单元名称 */ private static final String NAME = "openJPA"; public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory(NAME); EntityManager em = emf.createEntityManager(); User user = em.find(User.class, 2L); System.out.println(user); em.close(); emf.close(); System.out.println("finished."); } }
上面代码,仅仅演示了 JPA 中非常简单的根据主键ID查询实体的方法。关于 JPA 查询方法在后续章节将详细介绍;