JPA快速入门、小知识

JPA

JPA是一个ORM(对象关系映射)规范,是一组接口;

像Hibernate、open jpa、eclipse link就是jpa的一种实现

在springboot快速构建项目中的jpa依赖默认就使用的是Hibernate

1.引入依赖

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

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

2.SpringBoot配置JPA

server.port=8989

#数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=111111


#spring.jpa.properties.hibernate.hbm2ddl.auto=update

spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#让字段使用驼峰命名
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
#控制台显示sql
spring.jpa.show-sql=true
#格式化sql
spring.jpa.properties.hibernate.format_sql=true

3.jpa实体对象类

@Data
@Entity
@Table(name = "p_user")
@EntityListeners(AuditingEntityListener.class)
public class User {
    @Id
    @GenericGenerator(name = "myuuid", strategy = "uuid")
    @GeneratedValue(generator = "myuuid")
    @Column(name = "id")
    private String id;

    @Column(name = "name")
    private String name;

    @Column(name = "age")
    private int age;

    @CreatedDate
    @Column(name = "gmtCreate")
    private Date createTime;

    @LastModifiedDate
    @Column(name = "gmtModified")
    private Date updateTime;
}

解释:

image-20211207214030098

如果你要使用主键自增:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;

@GeneratedValue中strategy的四个选项:

-AUTO主键由程序控制, 是默认选项 ,不设置就是这个

-IDENTITY 主键由数据库生成, 采用数据库自增长, Oracle不支持这种方式

-SEQUENCE 通过数据库的序列产生主键, MYSQL 不支持

-Table 提供特定的数据库产生主键, 该方式更有利于数据库的移植

4.创建Mapper层接口

很简单,直接继承JpaRespository接口即可,其泛型填你要操作的实体类

public interface UserRespository extends JpaRepository<User,String> {
}

这样,你就有了jpa的基本crud了

5.写一个测试接口

1.查询所有:

@RestController
@CrossOrigin
public class TestController {
    @Autowired
    private UserRespository userRespository;

    @GetMapping("/test")
    public void test(){
        List<User> all = userRespository.findAll();
        for (User user : all) {
            System.out.println(user);
        }
        return;
    }
}

运行效果:

image-20211208210826971

2.分页查询

//简单的条件分页Example,根据user对象的属性进行匹配
//比如我设置了user的name为cc
//查询时,就生成where name=‘cc’的条件
User user = new User();
user.setName("cc");
Example<User> of = Example.of(user);
//分页查询
Page<User> page = userRespository.findAll(of, PageRequest.of(0, 2, Sort.by("id")));
for (User user1 : page.getContent()) {
    System.out.println(user1);
}

效果:

image-20211208212418835

需要注意的是jpa中是从第0页开始分页的’

如果你想使用一些特别的查询条件,比如模糊查询,就可以自定义查询条件:

User user = new User();
user.setName("c");

//自定义查询条件
ExampleMatcher matcher = ExampleMatcher
        .matching().
        withMatcher("name",ExampleMatcher.GenericPropertyMatchers.contains());
//查询条件对象
Example<User> of = Example.of(user, matcher);
//分页查询
Page<User> page = userRespository.findAll(of, PageRequest.of(0, 4, Sort.by("id")));
for (User user1 : page.getContent()) {
    System.out.println(user1);
}

此时就会根据name的值去数据库模糊匹配

image-20211208213808227

结果:

image-20211208213901277

如果你想降序排列:

Sort.by("id").descending()

3.API很多

image-20211208215347704

就不一个一个试了,结合自定义条件查询就能适用于很多情况了

4.JPA命名查询

什么叫命名查询?

JPA可以根据你Respository的接口的方法名来实现查询:

比如,你在Repository接口中定义了一个方法:

List<User> findByEmail(String email);

你不用做其它事,他就会帮我们根据邮箱查找数据,生成where email=?

这时官网爬的,大家可自行参考

关键词样本JPQL 片段
DistinctfindDistinctByLastnameAndFirstnameselect distinct … where x.lastname = ?1 and x.firstname = ?2
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is, EqualsfindByFirstname, findByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNull, NullfindByAge(Is)Null… where x.age is null
IsNotNull, NotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1(参数绑定了 append %
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1(参数绑定 prepended %
ContainingfindByFirstnameContaining… where x.firstname like ?1(参数绑定包裹在%
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection<Age> ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection<Age> ages)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstname) = UPPER(?1)

5.自己写sql:@Query

@Transactional
@Modifying
@Query(nativeQuery = true, value = "update t_bucket set isDelete=1 where id=?1 ")
int deleteBucket(String id);

6.一对一,一对多。。。。

很简单只需要在实体类中加上注解即可OneToOne、OneToMany

@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
@JoinColumn(name = "表外键")
private Dog dog;

CascadeType:

ALL,
PERSIST,
MERGE,
REMOVE,
REFRESH,
DETACH;
  • CascadeType.PERSIST:级联新增(又称级联保存):对order对象保存时也对items里的对象也会保存。对应EntityManager的presist方法。

    例子:只有A类新增时,会级联B对象新增。若B对象在数据库存(跟新)在则抛异常(让B变为持久态)

  • CascadeType.MERGE:级联合并(级联更新):若items属性修改了那么order对象保存时同时修改items里的对象。对应EntityManager的merge方法 。
    例子:指A类新增或者变化,会级联B对象(新增或者变化)

  • CascadeType.REMOVE:级联删除:对order对象删除也对items里的对象也会删除。对应EntityManager的remove方法。

    例子:REMOVE只有A类删除时,会级联删除B类;

  • CascadeType.REFRESH:级联刷新:获取order对象里也同时也重新获取最新的items时的对象。对应EntityManager的refresh(object)方法有效。即会重新查询数据库里的最新数据。

  • CascadeType.ALL:以上四种都是。

FetchType:

1、FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。

2、FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。

比方User类有两个属性,name跟address,就像百度知道,登录后用户名是需要显示出来的,此属性用到的几率极大,要马上到数据库查,用急加载;
而用户地址大多数情况下不需要显示出来,只有在查看用户资料是才需要显示,需要用了才查数据库,用懒加载就好了。所以,并不是一登录就把用户
的所有资料都加载到对象中,于是有了这两种加载模式。

以上仅是本人学习使用过程中觉得比较实用的,可能存在错误或不准确,第一次接触JPA,多多包含

若后续工作中使用到了JPA,我会把有用的东西更新到此文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了我的架构师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值