使用 Spring Data JPA 操作大量数据

批量删除区别

delete() 和 deleteInBatch()
deleteAll() 和 deleteAllInBatch()

普通删除方法会根据唯一标识字段,生成多条 SQL 语句,而有 InBatch 的方法只会生成一条 SQL 语句

写入大量数据

@Transactional
public void save100WEntities() {
    for (int i = 0; i < 1000; i++) {
        respsitory.save(1000Entities);

         entityManager.flush();
        entityManager.clear();
    }
}

读取大量数据

需要满足3个条件:

  1. ResultSetType 是 ResultSet.TYPE_FORWARD_ONLY
  2. ResultSetConcurrency 是 ResultSet.CONCUR_READ_ONLY
  3. FetchSize 是 Integer.MIN_VALUE
Statement statement = connection.createStatement(
        ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
statement.setFetchSize(Integer.MIN_VALUE);

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
    @QueryHints(value = @QueryHint(name = FETCH_SIZE, value = "" + Integer.MIN_VALUE))
    Stream<User> findByIdIsNotNull();
}

@Transactional
public void run() {
    try (Stream<User> stream = userRepository.findByIdIsNotNull()) {
        stream.forEach(user -> {
            System.out.println(user);
            entityManager.detach(user);
        });
    }
}
2018/2/26 posted in  Spring Boot

关于 MySQL 中 InnoDB 事务锁的一些理解

InnoDB 行锁

参考 MySQL · 引擎特性 · InnoDB 事务锁系统简介
Locks Set by Different SQL Statements in InnoDB

区间锁(LOCK_GAP)

锁住一段范围,不锁记录本身,通常表示两个索引记录之间,或者索引上的第一条记录之前,或者最后一条记录之后的锁。一般在 RR 隔离级别下会使用。

Next-Key 锁(LOCK_ORDINARY)

其实就是锁住 待插入记录本身 + 记录之前的 GAP,Next-Key 锁用于解决 RR 隔离级别下的幻读问题。

通常对于 UPDATE 或 DELETE 或 SELECT … FOR UPDATE 或 SELECT … IN SHARE MODE 操作:

  • 查询条件为唯一索引且是唯一等值查询时,只对记录本身加锁
  • 非唯一条件查询,或者查询会扫描到多条记录,加 Next-Key 锁
Read more   2017/6/8 posted in  Database

MySQL、SQL Server 和 Oracle 触发器的创建

场景:当 users 表在 insert,update,delete 时,在 users_log 表中记录变更的 id

MySQL

触发时机:BEFORE,AFTER
触发事件:INSERT,UPDATE,DELETE
NEW 和 OLD 关键字:

| action | NEW | OLD |
|--------|----------------|----------------|
| insert | 插入的新数据 | 无 |
| update | 修改为的新数据 | 被修改的原数据 |
| delete | 无 | 被删除的原数据 |

DELIMITER $
CREATE TRIGGER insert_user AFTER INSERT
ON users FOR EACH ROW 
BEGIN
    INSERT INTO users_log(user_id, action) VALUES(NEW.id, 'insert');
END$
DELIMITER ;
Read more   2016/6/11 posted in  Database

代理模式及 Java 实现动态代理

前提条件

public interface Animal {
    void say();

    void run(String addr);
}

public class Dog implements Animal {
    @Override
    public void say() {
        System.out.println("汪汪汪");
    }

    @Override
    public void run(String addr) {
        say();
        System.out.println("狗在" + addr + "跑");
    }
}
Read more   2016/4/23 posted in  Java

关于 MySQL 中 InnoDB 的 MVCC 的一些理解

Read more   2016/4/17 posted in  Database