JPA

配置文件

mysql8.0和5.7有区别

  • 如启动报错:Communications link failure
    The driver has not received any packets from the server. 则注意检查连接mysql版本
点击查看代码
## 数据源配置
 
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

## Spring Data JPA 配置 5.7的
 spring.jpa.database-platform=org.hibernate.dialect.MySQL57Dialect
##Spring Data JPA 配置 8.0的
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
## 运行时输出 jpa 执行的 sql 语句
## 打印sql
spring.jpa.show-sql=true


## 根据实体类自动生成数据表(SpringDataJPA可以自动生成数据表)
## create:每次运行项目会自动创建新表,如果之前已经存在,则删除,重新创建
## update:只会更新数据表
# create-drop,启动时生成表,停止时,把表删除!!!
spring.jpa.hibernate.ddl-auto=update
#jackson对日期时间格式化设置:时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
#jackson对日期时间格式化设置:时区设置
spring.jackson.time-zone=GMT+8

如何初始化数据库

# 控制spring.jpa.hibernate.ddl-auto=xxx是否执行
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

  • spring.jpa.hibernate.ddl-auto= 有5个属性
value值 含义
none 不做处理
create 每次加载会先删除上一次生成的表,哪怕2次没任何变化也要删,数据会丢失
create-drop 每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。即系统停止时,会删表,数据会丢失
update 每次启动先检查是否有表,无则创建,有再检查是否有新字段,无此字段则添加,老字段,列类型无法修改
validate 验证创建数据库表结构,只进行比较,不会创建新表,但是会插入新值

生产环境

spring.jpa.hibernate.ddl-auto=none
spring.jpa.generate-ddl=false

生产环境的数据不允许随便修改,属性类型有调整,可以新建个字段和属性,把原来的数据用脚本迁移过去

原生写法

  • load方法(代码中使用该对象时才查库)

User user = entityManager.getReference(User.class,1);
此时user是个代理对象

  • get方法(正常查询)

User user = entityManager.find(User.class,1);

实体类注解

点击查看代码
@Entity
@Data
@Table(name = "student")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long sid;

    @Column(length = 30,unique = true)
    private String name;

	// 属性在字段的实际类型
    @Column(columnDefinition = "char")
    private int age;

    @Column
    private String home;
}

@Entity 加在类上,表示类名和表名的映射
@Table类上,当类名和表名不同时使用
@GeneratedValue(strategy = GenerationType.AUTO) 主键的生产策略

IDENTITY :自增(oracle不支持)
AUTO: jpa自动选择合适的策略,(默认值)
SEQUENCE: 通过序列产生主键,通过@SequenceGenerator注解指定序列名(mysql不支持);
TABLE: 通过表产生主键,借由表模拟序列产生主键,此策略可以使应用更易于数据库移植

@Basic,属性和字段的映射,getXxx()默认即为@Basic。

fetch属性,optional属性,是否允许为null,默认true

@Column 加在属性、get方法上,属性名和字段名不同时,使用。

有unique,length等属性

@Transient 加在属性上,表中可以没有此属性的字段(javax.persistence包)

// 表的字段会为date
@Temporal(TemporalType.DATE) 日期的格式,精确到日(3种:DATE--date,TIME,TIMESTAMP--datetime)
private Date birthday;

原生sql

MP和JPA对比

实体类

jpa MP 备注
类上 @Entity(name = "distribution_task_temp") 或 @Table(name = "distribution_task_temp") 1.@TableName("tb_user") 表名和类名映射
主键属性 "@Id @GeneratedValue(generator = "system-uuid")@GenericGenerator(name = "system-uuid", strategy = "uuid")@Column(name = "id") @TableId(type= IdType.AUTO) 3
普通属性 @Column(name = "customer_id") @TableField

dao

栗子:
@Repository
public interface WriteOffRecordRepository extends JpaRepository<WriteOffRecord, Long>,
JpaSpecificationExecutor {

JPQL语法

@Query注意点
1:大多情况下需要将*改为别名
2:表名要改为类名
3:字段名改为属性名
4:修改、删除还需要加注解:@Modifying
5:想写原生sql设置属性nativeQuery = true,要用Obeject[]来接
6: 占位符默认和参数顺序保持一致

占位符不按参数顺序的写法,?数字:
image

  • 查一个列(泛型是属性的类型)
    image
  • 查多个列
    image

多对多

@ManyToMany
@JoinTable
image

image

一对多

多方表会创建外键(一方的主键)
@OneToMany(加在一方)
例子:@OneToMany(mappedBy = "classes", cascade=CascadeType.DETACH, fetch = FetchType.LAZY)

  • 属性“串联”: cascade=CascadeType

    • 增:CascadeType.PERSIST —–>save()
    • 删:对应CascadeType.REMOVE —–>delete()
    • 改:对应CascadeType.MERGE ——>update()
    • CascadeType.DETACH
  • 属性“获取” fetch=FetchType.EAGER 和LAZY

    • LAZY,访问该对象,才查询。
    • EAGER,立即查询

@ManyToOne(加在多端)
@JoinColumn 填写一方的属性名
下图是错误的示范,在一方,fetch=FetchType.Lazy会造成查询时报错,无法级联查出多方数据
image

查一方,自动级联查出多方
1:一方的注解:@OneToMany(mappedBy="一方在多方的属性名",fecth=FetchTypeEAGER),如果是LAZY,会报could not initialize proxy - no Session
2: 注意循环依赖问题(StackOverflowError),在多方排除一方(双引号里面是一方属性名)
image

一对一

@OneToOne

  • 实体类(截图中会自动创建外键)
    image

  • dao
    save(子对象和主对象都插入了)
    image

    删(删主对象,关联对象那行也别删了)
    image

高级用法

  • findBy
    属性名首字母大写
    参数默认按顺序
  • eq

/**
* 固定语法格式:findBy 加属性名首字母大写(where student0_.name=?)
* @param name
* @return
*/
List findByName(String name);

  • and
    image

  • 多字段组合
    findByNameLikeOrAgeBetween(String nam, int startAge, int endAge);

  • 文档
    startingWith,截图意思是,参数就要这样传:“jf%”
    image

  • 对比

jpa MP 备注
dao层 JpaRepository BaseMapper 对单表的curd方法

动态查询

重点

JpaSpecificationExecutor<T> 接口

类似于MP的IService
方法
image

Specification参数

类似于MP的QueryWarrper
image

Sort排序参数

image

PageRequest分页参数

image

问题

@Formula

  • 用法2:执行sql
    @Formula("select count(s.id) from order s where s.user_id=id")
  • 用法1:表中字段做函数运算
    @Formula("goods_sales_num + sham_sales_num")
    private Long allSalesNum;

@MappedSuperclass

@EntityListeners(AuditingEntityListener.class)

@DynamicInsert做什么的

默认true
Entity类中写@DynamicInsert(true)从而实现
在使用save函数保存新数据时如果实例对象某个属性为null时则不写入数据库中。
如果不使用此注解则会把null写入数据库中,数据库中该字段变为null值。

NamedEntityGraph做什么的

应用场景:N+1
用法
@NamedEntityGraph(name = "goodsInfo", attributeNodes = {@NamedAttributeNode("goodsInfo")})

@JoinColumn的属性用法

什么意思
@JoinColumn(name = "goods_info_id", insertable = false, updatable = false)

posted @ 2022-10-23 18:47  jf666new  阅读(213)  评论(0)    收藏  举报