SpringDataJPA——@Entity常用注解

@Entity实例常用注解

常用注解

@Id

  定义属性为数据库的主键,一个实体里面必须有一个,并且必须和 @GeneratedValue 配合使用和成对出现。

@IdClass

 利用外部类的联合主键,源码:
public @interface IdClass {
//联合主键的类
    Class value();
}

作为符合主键类:

  • 必须实现 Serializable 接口
  • 必须有默认的 public 无参数的构造方法
  • 必须覆盖 equals 和 hashCode 方法。equals 方法用于判断两个对象是否相同,EntityManger 通过 find 方法来查找 Entity 时,是根据 equals 的返回值来判断的

关联关系注解

@OneToMany一对多和@ManyToOne 多对一

public @interface OneToMany {
    Class targetEntity() default void.class;
 //cascade 级联操作策略:(CascadeType.PERSIST、CascadeType.REMOVE、CascadeType.REFRESH、CascadeType.MERGE、CascadeType.ALL)
如果不填,默认关系表不会产生任何影响。
    CascadeType[] cascade() default {};
//数据获取方式EAGER(立即加载)/LAZY(延迟加载)
    FetchType fetch() default LAZY;
    //关系被谁维护,单项的。注意:只有关系维护方才能操作两者的关系。
    String mappedBy() default "";
//是否级联删除。和CascadeType.REMOVE的效果一样。两种配置了一个就会自动级联删除
    boolean orphanRemoval() default false;
}
public @interface ManyToOne {
    Class targetEntity() default void.class;
    CascadeType[] cascade() default {};
    FetchType fetch() default EAGER;
    boolean optional() default true;
}

关联查询Left join、Inner join 与 @EntityGraph

  1. Left join & Inner join 问题

当使用 @ManyToMany、@ManyToOne、@OneToMany、@OneToOne 关联关系的时候,SQL 真正执行的时候都是由一条主表查询和 N 条子表查询组成的。这种查询效率一般比较低下,子对象有多少个就会执行 N+1 条 SQL。

有时候我们需要用到 Left Join 或者 Inner Join 来查询来提高效率,只能通过 @Query 的 JQPL 语法去实现Spring Data JPA 为了简单的提高查询率,引入了EntityGraph 的概念,可以解决 N+1 条 SQL 的问题

@EntityGraph

JPA 2.1 推出来的 @EntityGraph、 @NamedEntityGraph 用来提高查询效率,很好的解决了 N+1 条 SQL 的问题,两者需要配合起来使用,缺一不可。@NamedEntityGraph 配置在 @Entity 上面,而 @EntityGraph 配置在 Repository 的查询方法上面,但是我使用左外连接条件测试,使用这个注解执行查询时查询时间变长了

步骤如例子中所示:

  1. 先在 Entity 里面定义 @NamedEntityGraph,其他都不变,其中 @NamedAttributeNode 可以有多个,也可以有一个。

subgraphs:子图,举例子:假如Persion类entity里有private List user属性,被@OneToMany注解,但是User里有个字段Address addr,那么subgraphs里就是配置Address的信息,就是嵌套的意思
@NamedEntityGraph可以命名多组,并且可以通过subgraphs来控制字段要不要输出,

@Repeatable(NamedEntityGraphs.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NamedEntityGraph {
    //自己起一个名字,作为此定义的唯一标识,这样可以定义多组设置,根据这个名字来决定使用哪个,后面在dao层会用到
    String name() default "";
	//属性节点,就是Entity里被@OneToMany注解的属性
    NamedAttributeNode[] attributeNodes() default {};

    boolean includeAllAttributes() default false;
	//子图
    NamedSubgraph[] subgraphs() default {};
	//子类子图
    NamedSubgraph[] subclassSubgraphs() default {};
}
//子图里的字段你会输出
subgraphs = {
        @NamedSubgraph(name = "",attributeNodes = {
            @NamedAttributeNode(value = "",subgraph = "123")
        })
//子图字段会输出null
subgraphs = {
        @NamedSubgraph(name = "country",attributeNodes = {})
    }
  1. 只需要在查询方法上加 @EntityGraph 注解即可,其中 value 就是 @NamedEntityGraph 中的 Name,在实例配置看例子。

例子

  1.这里我建立两张表,user_relation表(表1),bd_copy表(表2),表1与表二通过peijectid字段具有一对多关系,第一次使用立即加载,返回结果没有问题,加载速度较慢,直接返回
  2. 换成延迟加载,发现dao层查询结果不经过处理直接返回给controller层会出现异常,如下
  3. 解决:除了eager,还没找到有效方法

延迟加载出现的异常:
failed to lazily initialize a collection of role: com.example.springboot.JPA.entity.UserCrawlRelationEntity.bdcTaskCopyEntityList, could not initialize proxy - no Session
failed to lazily initialize a collection of role: com.example.springboot.JPA.entity.UserCrawlRelationEntity.bdcTaskCopyEntityList, could not initialize proxy - no Session
未能延迟初始化角色集合:com.example.springboot.JPA.entity.UserCrawlRelationEntity.bdcTaskCopyEntityList,无法初始化代理 - 没有会话未能延迟初始化角色集合:com.example.springboot.JPA.entity.UserCrawlRelationEntity .bdcTaskCopyEntityList,无法初始化代理 - 没有会话

Dao层

@Repository
public interface UserCrawlRepository extends JpaRepository<UserCrawlRelationEntity,Long>, JpaSpecificationExecutor<UserCrawlRelationEntity> {

@Repository
public interface UserCrawlRepository extends JpaRepository<UserCrawlRelationEntity,Long>, JpaSpecificationExecutor<UserCrawlRelationEntity> {

    @EntityGraph(value = "UserCrawlRelationEntity.bdcTaskCopyEntityList")
    List<UserCrawlRelationEntity> queryByProjectIdEquals(String projectId);
   } 

Entity层

@Entity
@Table(name = "user_relation")
@Data
@NamedEntityGraph(name = "UserCrawlRelationEntity.bdcTaskCopyEntityList", attributeNodes = {
        @NamedAttributeNode(value = "bdcTaskCopyEntityList")
},subgraphs = {})
public class UserCrawlRelationEntity implements Serializable {


    private static final long serialVersionUID = -4918127590584092681L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    /**
     * 创建时间
     */
    @Column(name = "create_time")
    @CreatedDate
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /**
     * 更新时间
     */
    @Column(name = "update_time")
    @LastModifiedDate
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /**
     * 用户名
     */
    @Column(name = "user_name")
    private String userName;
   
    @Column(name = "projectid")
    private String projectId;

    //@JoinTable(name = "view_dbc",
    //        joinColumns = {
    //                @JoinColumn(name = "viewProjectId", referencedColumnName = "projectId")
    //        },
    //        inverseJoinColumns = {
    //        @JoinColumn(name = "bdcPto", referencedColumnName = "projectId")
    //})

    @OneToMany(targetEntity = BdcTaskCopyEntity.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "projectId", referencedColumnName = "projectId")
    Set<BdcTaskCopyEntity> bdcTaskCopyEntityList;


}

@Entity
@Table(name = "bd_copy")
@Data
@AllArgsConstructor
@NoArgsConstructor
@EntityListeners(value = AuditingEntityListener.class)
public class BdcEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "serviceid")
    private String serviceId;

  
    @Column(name = "updatetime")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @LastModifiedDate
    private String updateTime;

	@Column(name = "projectid")
    private String projectId;
    
    //@ManyToOne(targetEntity = UserCrawlRelationEntity.class,cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    //@JoinColumn(name = "projectId",referencedColumnName = "projectId")
    //private UserCrawlRelationEntity userCrawlRelation;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值