前言
这里主打JPA的注解版哦,不是xml版哦
适合小白的入门学习,是JPA的一些基础操作,高级特性后期更新
一、JPA的起源
JPA由EJB 3.0软件专家组开发,作为JSR-220实现的一部分。但它又不限于EJB 3.0,你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范,由此可见,经过这几年的实践探索,能够脱离容器独立运行,方便开发和测试的理念已经深入人心了。Hibernate3.2+、TopLink 10.1.3以及OpenJPA都提供了JPA的实现。
二、什么是JPA
JPA是Java Persistence API的简称,是Sun公司提出的Java持久化规范。它是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA是JCP组织发布的Java EE标准之一,因此任何声称符合JPA 标准的框架都遵循同样的架构,提供相同的访问API。
注意; JPA 是一套规范,不是一套产品,那么像Hibernate、TopLink、 JDO它们是一套产品,如果说这些产品实现了这个JPA规范,那么我们就可以称他们为JPA的实现产品。
三、JPA的优势
-
标准化
JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。 -
容器级特性的支持
JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。 -
简单方便
JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易地掌握。JPA基于非侵入式原则设计,因此可以很容易地和其它框架或者容器集成。 -
查询能力
JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。 -
高级特性
JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。
四、SpringBoot Data JPA
Spring Data JPA是Spring 基于ORM框架、JPA规范的基础上封装的一套JPA 应用框架,可以让开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增、删、改、查等在内的常用功能,且易于扩展,学习并使用Spring Data JPA可以极大提高开发效率。Spring Data JPA其实就是Spring 基于Hibernate 之上构建的JPA使用解决方案,方便在Spring Boot项目中使用JPA技术。
Spring Data JPA让我们解脱了DAO层的操作,基本上所有CRUD(添删改查)都可以依赖于它实现。
五、JPA的代码实战
1、JPA拥有哪些注解呢?
我们先来了解它的注解,然后进入代码实战
注解 | 解释 |
---|---|
@Entity | 声明类为实体或表。 |
@Table | 声明表名。 |
@Basic | 指定非约束明确的各个字段。 |
@Embedded | 指定类或它的值是一个可嵌入的类的实例的实体的属性。 |
@Id | 指定的类的属性,用于识别(一个表中的主键)。 |
@GeneratedValue | 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。 |
@Transient | 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。 |
@Column | 指定持久属性栏属性。 |
@SequenceGenerator | 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。 |
@TableGenerator | 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。 |
@AccessType | 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。 |
@JoinColumn | 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。 |
@UniqueConstraint | 指定的字段和用于主要或辅助表的唯一约束。 |
@ColumnResult | 参考使用select子句的SQL查询中的列名。 |
@ManyToMany | 定义了连接表之间的多对多一对多的关系。 |
@ManyToOne | 定义了连接表之间的多对一的关系。 |
@OneToMany | 定义了连接表之间存在一个一对多的关系。 |
@OneToOne | 定义了连接表之间有一个一对一的关系。 |
@NamedQueries | 指定命名查询的列表。 |
@NamedQuery | 指定使用静态名称的查询。 |
2、代码实战
2.1 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2.2 配置
#配置数据源相关信息
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/appinfodb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
#配置JPA相关信息(hibernate)
#数据库的方言,假如使用Oracle 就配置Oracle 的方言,MySql就配置MySql的方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
#日志中显示sql语句
spring.jpa.show-sql=true
#格式化sql语句让它在日志中跟美观的展示出来
spring.jpa.properties.hibernate.format_sql=true
2.3 创建实体类
@Data
@Entity//告诉JPA这是一个实体类(和数据表映射的类)
@Table(name="dev_user") //@Table来指定和哪个数据表对应;如果省略默认表名就是user;
public class DevUser {
@Id//这是一个主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//自增主键
private Long id;
@Column(name = "last_name",length = 50) //这是和数据表对应的一个列
private String devCode;
@Column //省略默认列名就是属性名
private String devName;
}
@Data注解可以帮我们生成getset方法,要注意的是不是jpa的注解哦,要自己去百度一下
2.4 DevUserRepository接口
public interface UserRepository extends JpaRepository<DevUser,Long> {
public List<DevUser> findByDevCode(String devCode);
//自定义QL
@Transactional//对事物的支持,操作超时等
@Modifying//如果是删除或者是修改就需要加上此注解
@Query("update DevUser d set d.devCode=?1 where d.id=?2")
public int modifyingDevCode(String devCode,Long id);
}
@Transactional 对事物的支持,操作超时等
@Modifying 如果是删除或者是修改就需要加上此注解
@Query 在注解内写HQL语句,@Query里面的1代表参数1,2代表参数2,以此内推,我们也可以使用@Param来支持命名参数,来提供代码的可读性和维护性,
例如
@Transactional//对事物的支持,操作超时等
@Modifying//如果是删除或者是修改就需要加上此注解
@Query("update DevUser d set d.devCode=:devCode where d.id=:id")
public int modifyingDevCode(@Param("devCode") String devCode,@Param("id") Long id);
2.5 编写测试类
@Resource
UserRepository userRepository;
@Test
public void tset() {
DevUser devUser = new DevUser();
devUser.setDevCode("123");
devUser.setDevPassword("1234567");
//插入数据
System.out.println("插入数据");
userRepository.save(devUser);
System.out.println(devUser);
//根据id删除
System.out.println("根据id删除");
userRepository.deleteById(3L);
System.out.println("删除成功");
//查询全部并用forEach输出
System.out.println("查询全部并用forEach输出");
userRepository.findAll().forEach(lists-> System.out.println(lists));
//修改
System.out.println("修改");
int num = userRepository.modifyingDevCode("friday", 4L);
System.out.println("修改成功:" + num);
}
自定义查询的方法命名可是有规则的哦,我列举出来了哦
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstnameIs,findByFirstnameEquals | … where x.firstname = ?1 |
Between | findByStartDateBetween | … where x.startDate between ?1 and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual | … where x.age ⇐ ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1 (parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended %) |
Containing | findByFirstnameContaining | … where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection age) | … where x.age not in ?1 |
TRUE | findByActiveTrue() | … where x.active = true |
FALSE | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(?1) |
小伙伴们大家快去练习一下吧,冲冲冲