本文主要介绍 JPA 的实际使用,相关的环境及软件信息如下:JPA 2.2(eclipselink 2.7.10、hibernate-entitymanager 5.6.10.Final、openjpa 3.2.2),JPA 3.0(eclipselink 3.0.2、hibernate-core-jakarta 5.6.10.Final)。
1、JPA 2.2 使用
工程目录结构如下:
1.1、引入依赖
这里使用 eclipselink 作为 JPA 的实现框架。
<dependency> <groupId>org.eclipse.persistencegroupId> <artifactId>org.eclipse.persistence.jpaartifactId> <version>2.7.10version> dependency>
其他的依赖可自行引入,如数据库驱动、lombok 等。
1.2、创建实体类
1.2.1、Student.java
package com.abc.demojpa.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
@Table(name = "a_student")
@NamedQuery(name = "queryAll", query = "select s from Student s")
public class Student {
@Id
@GeneratedValue
private Long id;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "modify_time")
private LocalDateTime modifyTime;
private String name;
private Integer age;
@Column(name = "home_address")
private String homeAddress;
}
1.2.2、BaseEntity.java
package com.abc.demojpa.entity;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@Data
//该类的属性都将映射到其子类的数据库字段中
@MappedSuperclass
public class BaseEntity {
@Id
@GeneratedValue
private Long id;
@Column(name = "create_time")
private LocalDateTime createTime;
}
1.2.3、Teacher.java
Teacher 继承了 BaseEntity,主要为了测试属性的继承。
package com.abc.demojpa.entity;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@NoArgsConstructor
@Data
@Entity
@Table(name = "a_teacher")
public class Teacher extends BaseEntity {
private String name;
private Integer age;
}
1.3、编写 JPA 配置文件 (persistence.xml)
该配置文件需放在 META-INF 目录下。
xml version="1.0" encoding="UTF-8"?> <persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"> <persistence-unit name="myUnit"> <provider>org.eclipse.persistence.jpa.PersistenceProviderprovider> <class>com.abc.demojpa.entity.Studentclass> <class>com.abc.demojpa.entity.Teacherclass> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://10.49.196.10:3306/test?useUnicode=true&characterEncoding=UTF-8"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="123456"/> <property name="eclipselink.logging.level" value="INFO" /> <property name="eclipselink.ddl-generation" value="create-or-extend-tables" /> properties> persistence-unit> persistence>
eclipselink 开头的配置是 eclipselink 自带的扩展配置,用于实现功能的增强;详细的扩展配置说明可参考官网说明:https://www.eclipse.org/eclipselink/documentation/2.7/jpa/extensions/toc.htm。
1.4、使用例子
1.4.1、插入实体
@Test
public void persist() {
entityManager.getTransaction().begin();
Student student = new Student();
student.setName("小明");
student.setCreateTime(LocalDateTime.now());
student.setModifyTime(LocalDateTime.now());
student.setAge(15);
student.setHomeAddress("江苏");
Student student2 = new Student();
student2.setName("小红");
student2.setAge(18);
student2.setHomeAddress("广东");
Teacher teacher = new Teacher();
teacher.setCreateTime(LocalDateTime.now());
teacher.setName("张三");
teacher.setAge(35);
entityManager.persist(student);
entityManager.persist(student2);
entityManager.persist(teacher);
entityManager.getTransaction().commit();
}
1.4.2、查询实体
@Test
public void find() {
Student student = entityManager.find(Student.class, 1501L);
logger.info("student={}", student);
}
1.4.3、更新实体(先查再更新)
@Test
public void modify() {
entityManager.getTransaction().begin();
Student student = entityManager.find(Student.class, 1501L);
student.setName("小明2");
entityManager.getTransaction().commit();
}
1.4.4、更新实体(直接根据id更新)
@Test
public void merge() {
entityManager.getTransaction().begin();
Student student = new Student();
student.setId(1501L);
student.setName("小明3");
student.setAge(16);
entityManager.merge(student);
entityManager.getTransaction().commit();
}
1.4.5、删除实体
@Test
public void remove() {
entityManager.getTransaction().begin();
Student student = entityManager.find(Student.class, 1501L);
entityManager.remove(student);
entityManager.getTransaction().commit();
}
1.4.6、JPQL 查询
@Test
public void select() {
//查询一个字段
Query query = entityManager.createQuery("select s.name from Student s where s.age>10", String.class);
List result = query.getResultList();
logger.info("result={}", result);
//查询多个字段 (?n 占位符:传统 ? 占位符的改良占位符,仅仅适应 JPQL 查询)
query = entityManager.createQuery("select s.name,s.homeAddress from Student s where s.age>?1 and s.name like ?2", Object[].class);
query.setParameter(1, 10);
query.setParameter(2, "%小%");
List result2 = query.getResultList();
for (Object[] arr : result2) {
String s = "";
for (Object o : arr) {
s += o.toString() + ",";
}
logger.info(s);
}
//查询对象 (:name 占位符:变量名形式的占位符,仅仅适应 JPQL 查询)
query = entityManager.createQuery("select s.name,s.homeAddress from Student s where s.age between :min and :max and s.name like '%小%' order by s.id", Student.class);
query.setParameter("min", 10);
query.setParameter("max", 40);
//设置结果的开始位置,最大记录条数,可用来实现分页
query.setFirstResult(0);
query.setMaxResults(10);
List result3 = query.getResultList();
logger.info("result3={}", result3);
//聚合操作
query = entityManager.createQuery("select max(s.age) from Student s");
Object result4 = query.getSingleResult();
logger.info("result4={}", result4);
//对应Student实体类中定义的静态查询"queryAll"
query = entityManager.createNamedQuery("queryAll");
List result5 = query.getResultList();
logger.info("result5={}", result5);
}
1.4.7、JPQL 更新
@Test
public void update() {
entityManager.getTransaction().begin();
Query query = entityManager.createQuery( "update Student SET age=16 where name='小明'");
query.executeUpdate();
entityManager.getTransaction().commit();
}
1.4.8、JPQL 删除
@Test
public void delete() {
entityManager.getTransaction().begin();
Query query = entityManager.createQuery( "delete from Student where id=1501");
query.executeUpdate();
entityManager.getTransaction().commit();
}
1.4.9、JPQL 本地查询,直接 SQL 语句查询数据
@Test
public void nativeSelect() {
Query query = entityManager.createNativeQuery("select s.* from a_student s where s.age>?", Student.class);
query.setParameter(1, 10);
List result = query.getResultList();
logger.info("result={}", result);
}
1.4.10、JPA 标准 API 使用一
类似 SQL:select name from student where name=’小明’
@Test
public void criteria() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(String.class);
Root root = criteriaQuery.from(Student.class);
criteriaQuery.select(root.get("name"));
criteriaQuery.where(criteriaBuilder.equal(root.get("name"), "小明"));
TypedQuery query = entityManager.createQuery(criteriaQuery);
List list = query.getResultList();
logger.info(list.toString());
}
1.4.11、JPA 标准 API 使用二
类似 SQL:select id,name,age from student where age>=10 order by age,name desc
@Test
public void criteria2() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Student.class);
Root root = criteriaQuery.from(Student.class);
//Student 实体类需要有对应的构造方法
criteriaQuery.multiselect(root.get("id"), root.get("name"), root.get("age"), root.get("homeAddress"));
criteriaQuery.where(criteriaBuilder.ge(root.get("age"), 10));
criteriaQuery.orderBy(criteriaBuilder.asc(root.get("age"))).orderBy(criteriaBuilder.desc(root.get("name")));
TypedQuery query = entityManager.createQuery(criteriaQuery);
List list = query.getResultList();
logger.info(list.toString());
}
1.4.12、JPA 标准 API 使用三
类似 SQL:select age,count(*) from student group by age having age
Original: https://www.cnblogs.com/wuyongyin/p/16516717.html
Author: 且行且码
Title: JPA 入门实战(2)–简单使用
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/620568/
转载文章受原作者版权保护。转载请注明原作者出处!