Spring Boot无法创建Session:PRIMARY_ID插入空值异常求助
嘿,我看你碰到了Spring Session插入会话数据时的主键NULL问题,这事儿我之前也遇到过——你的SPRING_SESSION表把PRIMARY_ID设成了非空主键,但Spring Session默认的插入SQL根本没包含这个字段,数据库当然会报错啦。
问题出在哪?
你自定义的表结构用了PRIMARY_ID作为主键,但Spring Session的JDBC存储默认只处理SESSION_ID、CREATION_TIME这些标准字段,完全不知道要给PRIMARY_ID赋值,所以插入时这个字段就是NULL,直接触发了数据库的非空约束。
怎么解决?
给你两个实用的方案,选哪个看你需求:
1. 让Spring Session适配你的表结构
如果想保留现有的表结构,就得告诉Spring Session要处理PRIMARY_ID字段。
Spring Boot环境下用属性配置最方便:
在application.properties里加这些配置,自定义插入SQL并生成主键:
# 指定会话表名 spring.session.jdbc.table-name=SPRING_SESSION # 禁止自动生成表结构(避免覆盖你的自定义表) spring.session.jdbc.initialize-schema=never # 自定义插入SQL,用UUID生成PRIMARY_ID(根据你的数据库换对应函数,比如SQL Server用NEWID()) spring.session.jdbc.insert-session-sql=INSERT INTO SPRING_SESSION (PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) VALUES (UUID(), ?, ?, ?, ?, ?, ?)
如果是非Spring Boot场景,就自定义SessionRepository:
写个继承自JdbcOperationsSessionRepository的子类,重写插入方法手动赋值PRIMARY_ID:
@Repository public class CustomJdbcSessionRepository extends JdbcOperationsSessionRepository { public CustomJdbcSessionRepository(JdbcOperations jdbcOperations, PlatformTransactionManager transactionManager) { super(jdbcOperations, transactionManager); setTableName("SPRING_SESSION"); } @Override protected void insertSession(Session session) { // 生成主键ID String primaryId = UUID.randomUUID().toString(); getJdbcOperations().update( "INSERT INTO SPRING_SESSION (PRIMARY_ID, SESSION_ID, CREATION_TIME, LAST_ACCESS_TIME, MAX_INACTIVE_INTERVAL, EXPIRY_TIME, PRINCIPAL_NAME) VALUES (?, ?, ?, ?, ?, ?, ?)", primaryId, session.getId(), session.getCreationTime(), session.getLastAccessedTime(), session.getMaxInactiveInterval().getSeconds(), session.getCreationTime() + session.getMaxInactiveInterval().toMillis(), session.getPrincipalName() ); } }
然后在配置类里把这个自定义的Repository注册成Bean,替换默认的实现就行。
2. 修改表结构适配Spring Session默认逻辑
要是不想改代码配置,那就调整表结构,把SESSION_ID设为主键(这也是Spring Session默认的表设计):
-- 先删除原主键 ALTER TABLE SPRING_SESSION DROP PRIMARY KEY; -- 把SESSION_ID设为主键 ALTER TABLE SPRING_SESSION ADD CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (SESSION_ID); -- 删除原来的SESSION_ID唯一索引(因为主键已经唯一了) DROP INDEX SPRING_SESSION_IX1 ON SPRING_SESSION; -- 更新关联表的外键,指向新的主键 ALTER TABLE SPRING_SESSION_ATTRIBUTES DROP CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK; ALTER TABLE SPRING_SESSION_ATTRIBUTES ADD CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(SESSION_ID) ON DELETE CASCADE; -- 要是不用PRIMARY_ID了,就删掉它 ALTER TABLE SPRING_SESSION DROP COLUMN PRIMARY_ID;
这样改完,Spring Session的默认插入逻辑就能正常跑起来,不用额外配置。
最后验证下
不管用哪个方案,重启应用后试试创建会话(比如登录),看看SPRING_SESSION表能不能正常插入数据,要是没再报NULL错误,那就搞定啦!
内容的提问来源于stack exchange,提问作者Chetan




