JPA介绍
- JPA是Sun公司官方提出的Java持久化规范。它提供了一种对象/关系映射的工具管理Java中的关系型数据,主要是为了简化持久化开发工作和整合ORM技术。
- ORM: 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
Spring Data JPA
Spring Data JPA是Spring在ORM框架、JPA规范的基础上封装的一套JPA应用框架,提供了增删改查等常用功能。
@Entity(name="comment")
public class Discuss{
@Id
@GeneratedValue(Strategy=GenerationType.IDENTITY)
private Integer id;
@Column(name="ArticleId")
private Integer ArticleId;
//省略set get方法
}
注解说明:
@Entity(name=“comment”) | 标注要与数据库做映射的实体类,默认情况下,数据库名称就是首字母小写的类名,也可以用name属性进行指定映射表名 |
---|---|
@Id | 标注在类属性或者getter方法,表明某一个属性对应表中的主键 |
@GeneratedValue | 与@Id注解标注在同一位置,表示属性对应主键的生成策略,可省略。(Strategy=GenerationType.IDENTITY)为具体生成策略,TABLE、SEQUENCE、IDENTITY、AUTO四种方式 |
@Column(name=“ArticleId”) | 标注在属性上,当类属性与表的字段名不同时,使用name指定表字段名 |
public interface DiscussRepository extends JpaRepository<Discuss,Integer>{
// 基本的查询方法,为JPA中支持的方式,查询author非空的Disscuss评论信息
public List<Discuss> findByAuthorNotNull();
// @Query注解引入一个SQL语句,通过文章分页ID查询Discuss评论信息
@Query("select c from comment c where c.ArticleId = ?1")
public List<Discuss> getDiscussPaged(Integer articleId,Pageable pageable);
// 与上一条查询语句的区别为 加入vlaue和nativeQuery编写原生Sql语句
@Query(value="select * from comment where articleId = ?1",nativeQuery=true)
public List<Discuss> getDiscussPaged2(Integer articleId,Pageable pagebale);
// @Transactional:支持事务管理
@Transactional
// @Modifying:支持数据变更
@Modifying
@Query("update comment c set c.author=?1 where c.id=?2")
public int updateDiscuss(String author,Integer id);
@Transactional
@Modifying
@Query("delete comment c where c.id=?1")
public int deleteDiscuss(Integer id);
}
- 使用Spring Data JPA的Repository接口方法时需要注意
- 自定义Repository接口,必须继承XXRepository<I,ID>接口,T为要操作的实体类,ID为实体类主键数据类型。
- Repository接口是顶级父类接口,该接口没有声明任何方法;CrudRepository接口是Repository接口的继承接口之一,包含了一些基本的CRUD方法;
- PagingAndSortingRepository接口继承了CrudRepository接口同时,还提供了分页和排序方法;QueryByExampleExecutor接口是进行条件封装查询的顶级父类接口,允许通过Example实例进行复杂条件查询。
- JPARepository接口同时继承了PagingAndSortingRepository接口和QueryByExampleExecutor接口,并提供了一些数据操作方法。
- Spring Data JPA支持的方法名
官网查询地址
- 自定义的Repository接口中,针对数据的变更操作(修改、删除),无论是否使用@Query注解,都必须在方法上添加@Transactional注解进行事务管理否则会出现InvalidDataAccessApiUsageException异常。如果调用该接口的业务层添加了@Transactional注解,接口层可省略。除@Transactional注解外还需加入@Modifying注解表示数据变更。
- 使用Example实例进行复杂条件查询
//示例:
//1.使用Example精确匹配查询条件
Discuss discuss = new Discuss();
discuss.setAuthor("张三");
Example<Discuss> example = Example.of(discuss);
List<Discuss> list = repository.findAll(example);
//2.使用ExampleMatcher模糊匹配查询条件
Discuss discuss = new Discuss();
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("author",startsWith());
Example<Discuss> example = Example.of(discuss,matcher);
List<Discuss> list = repository.findAll(example);
使用SpringBoot整合JPA
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
# JPA Configuration
#spring.jpa.database=mysql
#spring.jpa.show-sql=true
#spring.jpa.generate-ddl=true
#JPA的正向工程
spring.jpa.hibernate.ddl-auto=update
#jpa 命名:开启无修改命名,该处因为我的数据库没有采用_的写法,所以需采用第一种无修改命名
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#遇到大写字母 加”_”的命名
#spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
@Entity(name="comment")
public class Discuss {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String content;
private String author;
// @Column(name = "articleId") 指定映射的表字段名
private Integer articleId;
//省略 set get toString
}
import com.example.jpa03chapter.domain.Discuss;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
import java.awt.print.Pageable;
import java.util.List;
public interface DiscussRepository extends JpaRepository<Discuss,Integer> {
//1.查询author非空的Discuss评论集合
public List<Discuss> findByAuthorNotNull();
//2.根据文章id问也查询Discuss评论集合
@Query("select c from comment c where c.articleId=?1")
public List<Discuss> getDiscussPaged(Integer articleId, Pageable pageable);
//3.使用元素SQL语句,根据文章id分页查询Discuss评论集合
@Query(value = "select * from comment where articleId=?1",nativeQuery = true)
public List<Discuss> getDiscussPaged2(Integer articleId,Pageable pageable);
//4.根据评论id修改评论作者author
@Transactional
@Modifying
@Query("update comment c set c.author=?1 where c.id=?2")
public int updateDiscuss(String author,Integer id);
//5.根据评论id删除评论
@Transactional
@Modifying
@Query("delete from comment c where id=?1")
public int deleteDiscuss(Integer id);
}
@RunWith(SpringRunner.class)
@SpringBootTest
class Jpa03chapterApplicationTests {
@Autowired
private DiscussRepository repository;
// 1.使用repository内部方法进行数据操作
@Test
void selectComment() {
//Optional:可以为Null的容器 8的新特性
Optional<Discuss> optional = repository.findById(1);
// if(optional.isPresent()){
// System.out.println(optional.get());
// }
optional.ifPresent(System.out::println);
}
//2.使用方法名关键字进行数据操作
@Test
public void selectCommentByKeys(){
List<Discuss> list = repository.findByAuthorNotNull();
System.out.println(list);
}
//3.使用Query注解进行数据操作
@Test
public void selectCommentPaged(){
Pageable pageable = PageRequest.of(0,3);
List<Discuss> allPaged = repository.getDiscussPaged(1,pageable);
System.out.println(allPaged);
}
//4.使用Example封装参数进行数据查询操作
@Test
public void selectCommentByExample(){
Discuss discuss = new Discuss();
discuss.setAuthor("张三");
Example<Discuss> example = Example.of(discuss);
List<Discuss> list = repository.findAll(example);
System.out.println(list);
}
@Test
public void selectCommentByExampleMatcher(){
Discuss discuss = new Discuss();
discuss.setAuthor("张");
//matcher用法注意 参考官网写法
ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("author",match -> match.startsWith());
Example<Discuss> example = Example.of(discuss,matcher);
List<Discuss>list=repository.findAll(example);
System.out.println(list);
}
}