小小白学SpringBoot(五) ——整合 JPA

小白一个,文章中可能说的不严谨或者错的地方,请指出我立马改,我超快的,嘿嘿。

JPA介绍

Spring Date JPA 同样是对数据库进行的操作
与Mybatis不同的是,JPA自定义的接口必须继承 XXRepository,通常选择继承JpaRepository

Repository接口继承结构图:
在这里插入图片描述
XXRepository<T,ID>
T:表示要操作的实体类
ID:实体类中主键的类型

  • Repository:空接口,表名任何继承它的均为仓库接口类
  • CrudRepository:提供了一组CRUD相关的方法
  • PagingAndSortingRepository:提供了一组分页、排序相关的方法
  • QueryByExample:可以通过Example实例执行复杂条件语句
  • JpaRepository:实现一组JPA规范相关的方法

JPA支持方法名关键字查询
在这里插入图片描述
可以免去SQL语句的编写

实例编写

前提:
如果是和之前的项目写在一起,记得将 mybatis依赖 及所有与mybatis相关的代码进行注释 ;
如果是新项目,记得加 数据库连接 和 mysql依赖

此项目我们依然使用(四)中的 t_article 数据表

1、加入相应的pom依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>  
</dependency>

2、编写实体类

package com.zknu.demo.model;

import javax.persistence.*;

@Entity(name = "t_article")
// 标注与之映射的数据表 ,默认为首字母小写的类名,也可用name属性就行指定
public class Discuss {
    @Id    //   标注主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    //  主键的生成策略 IDENTITY为自动递增
    private Integer id;

    private String title;

    @Column(name = "content")
    private String desc;
    // 如果字段名与属性名不一致,使用Column 指定表中的字段名所对应的类的属性名

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    @Override
    public String toString() {
        return "Discuss{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

Column中字段名会报红没关系

3、编写Repository接口

package com.zknu.demo.mapper;

import com.zknu.demo.model.Discuss;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import javax.transaction.Transactional;
import java.awt.print.Pageable;
import java.util.List;

//  Discuss为刚刚编写的实体类,Integer是实体类中主键的数据类型
public interface DiscussRepository extends JpaRepository<Discuss,Integer>{
    public List<Discuss> findByDescNotNull();
    // 使用JPA中的方法名关键字
    //  表示:查找表中 desc(即 content)不为空的所有数据

    @Query("select c from t_article c where c.id = ?1")
    public List<Discuss> getDiscussByPaged(Integer id, Pageable pageable);
    // 使用Query注解,可以使用分页查询
    // SQL语句语法不变
    // ?1 表示传的第一个参数
    //  等同于 MyBatis中 #{参数}

    @Query(value="select * from t_article where id = ?1",nativeQuery = true)
    public List<Discuss> selectDiscuss2(Integer id);
    // nativeQuery= true 编写原生的SQL语句

    @Transactional  //  支持事务管理
    @Modifying     //  支持数据变更
    @Query("update t_article set title = ?2 where id = ?1")
    public int updateDiscuss(String title,Integer id);

 	@Transactional
    @Modifying
    @Query(value = "insert into t_article(title,content) values (?1,?2)",nativeQuery = true)
    public int insertDiscuss(String title,String desc);

    @Transactional
    @Modifying
    @Query("delete from t_article where id = ?1")
    public int deleteDiscuss(Integer id);
}

注意:
在进行 增加、修改、删除操作时,必须加上
@Transactional 和 @Modifying 两个注解

insert 语句必须使用value,因为JPA的jpql不支持insert into
insert into 的字段名必须使用数据表中的字段名,不可使用被@Column标注过的字段名
eg. insert into(title,content), 此时的 content 不能用 desc

4、测试类

使用JPA内部方法进行数据操作

@Autowired
    private DiscussRepository repository;
@Test
    public void selectByJPA(){
        System.out.println(repository.findById(1));
    }

findById方法并不是我们自定义的方法,而是JPA的内部方法

运行结果在这里插入图片描述
使用自定义方法

插入语句

@Test
    public void insertDiscuss(){
        repository.insertDiscuss("入门","入门精通");
        repository.insertDiscuss("入门","门入");
    }

使用Example进行数据查询操作

Example的查询主要是 JpaRepository 继承的 QueryByExampleExecutor 接口的方法

Example包含 probe、matcher 两部分

probe 是实体类,用于查询的参对象
matcher 是查找规则

上面的测试中插入了两条语句,我们用 “入” 这个字来比较一下Example和ExampleMarcher的区别

数据表如下图
在这里插入图片描述

Example完整查询

测试类:

@Test
public void selectByExample(){
        Discuss discuss = new Discuss();
        discuss.setDesc("入门");
        Example<Discuss> example = Example.of(discuss);
        System.out.println(repository.findAll(example));
    }

Example.of 相当于实例化 Example对象

运行结果
在这里插入图片描述
结果只有一行数据
所以这个测试类查找的是 desc(即 content)中值为 “入门” 的数据

等价于sql语句:

SELECT * FROM t_article where content = "入门"

ExampleMatcher模糊查询

测试类:

@Test
    public void selectByExample2(){
        Discuss discuss = new Discuss();
        discuss.setDesc("入");
        ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("desc",ExampleMatcher.GenericPropertyMatchers.contains());
        Example<Discuss> example = Example.of(discuss,matcher);
        System.out.println(repository.findAll(example));
    }

运行结果
在这里插入图片描述
结果有这三条数据
在这里插入图片描述
所以,此测试类表示 desc(即 content)中值包含 “入” 的所有数据

等价于sql语句:

SELECT * FROM t_article where content LIKE '%入%'

ExampleMatcher.matching().withMatcher(“desc”,ExampleMatcher.GenericPropertyMatchers.contains()
表示在字段 desc 中查找以包含为条件的数据

除 contains() 外,常用的还有:

  • startsWith() 以xxx为开头
  • endsWith() 以xxx为结尾
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值