roothk nga gipatik nga mga artikulo

事情是这样的, 在项目使用中我们经常需要用到分页查询的功能, 但是Oracle直接分页查询在存在排序的情况下会出现分页错乱的情况

怎么解决呢??
-- 原始SQL
SELECT  FROM XXXX WHERE A='B' ORDER BY ID LIMIT 0, 100
-- 改造后
select * from (select oracleB.*, rownum rowno from (
    -- 这里其实就是把原始SQL的分页去掉, 只保留排序, 让分页在外面
    SELECT  FROM XXXX WHERE A='B' ORDER BY ID
) oracleB where rownum <= 100) oracleC where oracleC.rowno > 0

docker创建数据库

--name oracle-19c // 指定容器名称
-p 1521:1521 // 绑定端口
-e ORACLE_SID=hk // 指定oracle的sid
-e ORACLE_PDB=root // 指定pdb的用户名
-e ORACLE_PWD=123123 // 指定pdb的密码
-v /f/docker/oracle/oradata:/opt/oracle/oradata // 指定路径映射 宿主机文件路径:容器文件路径
zqldocker/oracle:oracle-19cdocker // 指定docker镜像名
exec // 命令行
-it // 后台运行
/bin/bash // 命令行
docker run --name oracle-19c -p 1521:1521 -p 5500:5500 -e ORACLE_SID=hk -e ORACLE_PDB=root -e ORACLE_PWD=123123 -v /f/docker/oracle/oradata:/opt/oracle/oradata zqldocker/oracle:oracle-19cdocker exec -it oracle-19c /bin/bash

登录数据库

进入到docker容器后执行
sqlplus / as sysdba

查看文件保存地址

用于查看文件保存的位置
例如返回了 /u01/app/oracle/oradata/XE/dba.dbf 等
那么下面创建数据库的路径前缀就是 '/u01/app/oracle/oradata/XE/'
路径最后的'XE'其实就是对应的serviceName
select name from v$datafile;

创建库

下面创建语句可以知道信息

  1. DATAFILE 数据保存文件保存地址
  2. SIZE 100M 初始化大小
  3. AUTOEXTEND ON NEXT 32M 自动扩充, 一次扩充32M
  4. MAXSIZE 500M 最大500M
CREATE TABLESPACE admin_db LOGGING DATAFILE '/u01/app/oracle/oradata/XE/admin_db.dbf' SIZE 100M AUTOEXTEND ON NEXT 32M MAXSIZE 500M EXTENT MANAGEMENT LOCAL;

创建临时库

create temporary tablespace admin_db_temp tempfile '/u01/app/oracle/oradata/XE/admin_db_temp.dbf' size 100m autoextend on next 32m maxsize 500m extent management local;

创建用户

> 此处创建用户'admin_db', 密码123123, 并指定数据库和临时库
create user admin_db identified by 123123 default tablespace admin_db temporary tablespace admin_db_temp;

设置用户权限

给admin_db用户指定dba权限
grant dba to admin_db;

连接数据库

// Spring Boot 2
spring.datasource.url=jdbc:oracle:thin:@127.0.0.1:1521:XE
spring.datasource.username=ADMIN_DB
spring.datasource.password=123123

出现问题

org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query

问题原因: 缺少@Transactional注解 (解决方案: 下面二选一即可)

1. 相对Repository加入
@Repository
@Transactional
public interface MessagePluginSendParamRepository extends JpaRepository<Bean, Long> {
    // xxxx
}
2. 相对应的Service加入
@Service
@Transactional
public class Service {
    // xxxx
}

出现问题

在父级线程设置了对象值
// Class1
// 查询
A a = repository.findById(1L).orEles(null);
// 设置了B
a.setB("B");
// 保存
repository.save(a);
// Async调用方法
async(a.getId());

// Class2
@Async
public void async(Long id) {
    A a = repository.findById(id).orEles(null);
    // 这里获取的不是B
    a.getB();
}

问题原因: JPA缓存导致

1. 对象保存时使用.saveAndFlush(S s);
repository.save(a); -> repository.saveAndFlush(a);
2. 设置Transactional
@Transactional -> @Transactional(readOnly = false)
3. 修改Repository的Update方法
@Modifying(clearAutomatically=true)
以上方法都会清除JPA的一级缓存

服用方式

public class Test {

    // 计数器
    public static LongAdder a = new LongAdder();

    // 异步方法
    public void addTest() {
        a.inrcement();// 等于a.add(1L);
    }

    // 异步方法
    public void subtractionTest() {
        a.decrement();// 等于a.add(-1L);
    }

    // 获取
    public Long getSum() {
       return a.sum();
    }

}