zhangzhenhuajack / spring-data-jpa-guide

spring-data-jpa-guide,Spring Data JPA实战,SpringDataJpa详解
http://www.jackzhang.cn/spring-data-jpa-guide/
379 stars 164 forks source link

解决save的时候不产生select语句,直接insert,提高批量操作是提升insert的效率 #31

Open zhangzhenhuajack opened 3 years ago

zhangzhenhuajack commented 3 years ago

第一步实体 implements Persistable, Serializable

第二步重写 isNew方法即可;

参考如下实体:

@Builder
@Getter
@Setter
@ToString
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(catalog = "user_gold", name = "user_goldjours_shard", indexes = {@Index(unique = true, columnList = "business_code_hash", name = "ux_on_business_code_hash"), @Index(columnList = "uuid,context_type,context_id", name = "idx_on_uuid_and_context_type_and_context_id"), @Index(columnList = "uuid,reason", name = "idx_on_uuid_and_reason")})
@org.hibernate.annotations.Table(appliesTo = "user_goldjours_shard", comment = "用户金贝流水拆分表")//为了给表添加注释
@EntityListeners(AuditingEntityListener.class)
public class UserGoldJoursShard implements Persistable<Long>, Serializable {

    private static final long serialVersionUID = 2225926240419540529L;

    /**
     * 利用hibernate 的 table generate id策略生成id,防止表与表之间ID冲突
     */
    @Column(nullable = false)
    @Id
    private Long id;
    @Column(columnDefinition = "varchar(255) DEFAULT NULL COMMENT '用户的 UUID'")
    private String uuid;
    @Column(columnDefinition = "int(11) DEFAULT NULL COMMENT '变动前数量'")
    private Long currentAmount;

    @Version
    private Long version; //必须包含version字段,解决detached entity passed to persist异常
    @Transient
    boolean defaultNew = false;

    @Override
    public boolean isNew() {
        return null == getId() || defaultNew;
    }

    public void setDefaultNew(boolean defaultNew) {
        this.defaultNew = defaultNew;
    }
}

当新增UserGoldJoursShard对象的时候设置defaultNew=true,调用实例如下:

    @Transient
    public UserGoldJoursShard initUserGoldShell() {
        UserGoldJoursShard userGoldShell = new UserGoldJoursShard();
        BeanUtils.copyProperties(this, userGoldShell);
        userGoldShell.setId(this.getId());
        //解决insert之前生成select查询的问题
        userGoldShell.setDefaultNew(true);
        //保留老表ID,防止异常情况需要更新回来
        userGoldShell.setOldTableId(getId());
        return userGoldShell;
    }
zhangzhenhuajack commented 2 years ago
spring.jpa.properties.hibernate.jdbc.batch_size=100
spring.jpa.properties.hibernate.order_inserts=true

The first property tells Hibernate to collect inserts in batches of four. The order_inserts property tells Hibernate to take the time to group inserts by entity, creating larger batches.

zhangzhenhuajack commented 2 years ago

同时需要注意控制好事务大小

zhangzhenhuajack commented 1 year ago

开启监控 spring.jpa.properties.hibernate.generate_statistics=true

16577314 nanoseconds spent preparing 100 JDBC statements;
2207548 nanoseconds spent executing 100 JDBC statements;
2003005 nanoseconds spent executing 1 JDBC batches;
zhangzhenhuajack commented 1 year ago

参考:https://github.com/zhangzhenhuajack/spring-data-jpa-guide/tree/master/2.3/jpa_id_generator_batch_insert

zhangzhenhuajack commented 1 year ago

image