You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot修改PersistentTokenRepository的Catalog存储persistent_logins表

问题描述

我正在使用SpringBoot,通过以下配置启用持久化认证机制:

@Bean
public PersistentTokenRepository persistentTokenRepository()
{
    JdbcTokenRepositoryImpl tokenRepo = new JdbcTokenRepositoryImpl();
    tokenRepo.setDataSource(dataSource);
    return tokenRepo;
}

当前数据源包含data和useraccount两个catalog,默认情况下PersistentTokenRepository会在主catalog「data」中查找,但我希望将persistent_logins表存储在「useraccount」中,因此编写了如下实体类:

@Entity(name="PersistentLogin")
@Table(name = "persistent_logins", catalog = "useraccount")
@Data
public class PersistentLogin implements Serializable
{  
 @Id
 private String series;
 private String username;
 private String token;
 private Timestamp last_used;  
}

但问题是系统始终在主catalog中查找persistent_logins表,请问有什么方法可以修改这个设置?

解决方案

你编写的PersistentLogin实体类不会被JdbcTokenRepositoryImpl采用——这个实现类是通过原生JDBC执行硬编码SQL来操作表的,完全不依赖JPA的实体映射配置。要让它指向useraccount catalog下的表,有两种直接可行的方法:

方法一:设置表名前缀(推荐)

JdbcTokenRepositoryImpl提供了setTablePrefix()方法,直接指定包含catalog的前缀即可让SQL定位到目标表:

@Bean
public PersistentTokenRepository persistentTokenRepository()
{
    JdbcTokenRepositoryImpl tokenRepo = new JdbcTokenRepositoryImpl();
    tokenRepo.setDataSource(dataSource);
    // 前缀带上catalog,格式为「catalog.」
    tokenRepo.setTablePrefix("useraccount.");
    return tokenRepo;
}

配置后,框架生成的SQL会自动变为SELECT ... FROM useraccount.persistent_logins ...,直接访问目标catalog下的表。

方法二:继承重写SQL语句(灵活定制)

如果需要更个性化的SQL调整,可以继承JdbcTokenRepositoryImpl并替换它的SQL属性:

public class CustomJdbcTokenRepository extends JdbcTokenRepositoryImpl {
    @Override
    protected void initDao() {
        super.initDao();
        String targetTable = "useraccount.persistent_logins";
        // 替换所有操作表的SQL语句
        this.setCreateTableSql("CREATE TABLE IF NOT EXISTS " + targetTable + " (series VARCHAR(64) PRIMARY KEY, username VARCHAR(64) NOT NULL, token VARCHAR(64) NOT NULL, last_used TIMESTAMP NOT NULL)");
        this.setInsertTokenSql("INSERT INTO " + targetTable + " (series, username, token, last_used) VALUES (?, ?, ?, ?)");
        this.setUpdateTokenSql("UPDATE " + targetTable + " SET token = ?, last_used = ? WHERE series = ?");
        this.setRemoveUserTokensSql("DELETE FROM " + targetTable + " WHERE username = ?");
        this.setGetTokenSql("SELECT username, series, token, last_used FROM " + targetTable + " WHERE series = ?");
    }
}

然后在配置类中使用这个自定义实现:

@Bean
public PersistentTokenRepository persistentTokenRepository()
{
    CustomJdbcTokenRepository tokenRepo = new CustomJdbcTokenRepository();
    tokenRepo.setDataSource(dataSource);
    return tokenRepo;
}

注意:不同数据库对Catalog/Schema的语法可能有差异(比如MySQL中Catalog和Schema基本等价,Oracle中Schema对应用户),需要根据你的数据库类型调整表名的格式。

内容的提问来源于stack exchange,提问作者Discipulos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:21:32