org.apache.shiro.session.UnknownSessionException--jpa查询语句自动变成了delete

本文探讨了在使用Shiro进行权限认证时遇到的UnknownSessionException异常,及通过NativeQuery执行查询语句时意外触发数据修改操作的问题。作者详细记录了问题排查过程,包括异常堆栈分析、数据库数据检查、代码逻辑审查,最终定位到实体更改导致的事务冲突,并提出了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       项目一直用shiro做权限认证,今天碰到了一个问题,一个原本正常的项目,因为更新,忽然间登录不上了,看错误提示,显示如下:

Exception occurred during processing request: org.apache.shiro.session.UnknownSessionException: There is no session with id [67a486f5-f495-4359-af2c-143ff253b514]

可是程序更新的内容并不涉及shiro部分,百思不得其解。后来再往上翻,又发现了一个异常,定位异常,又发现了自己之前就百思不得其解的一个问题,我好好的一个查询语句,一到执行,就去执行一个delete语句,然后查询函数上没有标注事务,所以执行不成功,报异常。

2018-08-31 12:11:48,244 [http-8811-3] ERROR [jdbc.sqltiming] - 22. PreparedStatement.executeUpdate() FAILED! delete from mg_sys_user_role where user_id=7211 and role_id=66 
 {FAILED after 0 msec}
java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
...
2018-08-31 12:11:48,246 [http-8811-3] WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - SQL Error: 0, SQLState: S1009
2018-08-31 12:11:48,246 [http-8811-3] ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - Connection is read-only. Queries leading to data modification are not allowed
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute statement
...
Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
...
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
...
Caused by: javax.persistence.RollbackException: Transaction marked as rollbackOnly

然而,定位异常发生的地方,不过是一个再简单不过的查询函数,只不过用的是NativeQuery :

public Set<String> findPermission(String roleids) {
		try {
			Set<String> permissions = new HashSet<String>();
			String queryStr = "select permission from mg_sys_role_permission where role_id in ("
					+ roleids + ")";
			Query query = em.createNativeQuery(queryStr);
			List<String> perms = (List<String>) query.getResultList();
			permissions.addAll(perms);
			perms.clear();
			perms=null;
			return permissions;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

设置断点,每执行到这个函数的getResultList后,便报上述异常。

       之前也碰到过类似的问题,也是一个查找语句,也用的是NativeQuery,不晓得为何最终会衍生一个update语句,之前博客也有记录,解决的方案是将NativeQuery改为标准Query执行,便可以了。可这个方法在这里行不通了,因为我这里用到的表并未做实体映射,如果再改实体类,未免改动太多,再说,我之前程序登录一直正常,这次不正常,不应该是程序上改动的问题,肯定跟某些数据有关。

       这个函数的用意是根据用户对应的role_id(会是多个),查找用户对应的权限。于是核对数据库中数据,发现当前登录用户对应的role_id为三个,但在这个函数查找时,只查找两个,查另外一个role_id对应记录状态,发现这条记录状态为不可用,改为可用就不再出现这个问题。

************************

       上面的问题其实我没写完,当时写了一半去忙了,回来也忘记补上了,时至今日,当初想说什么也忘了。

        我今天又来续写这篇文章,实在是又碰到了这个问题。

        如果说前几次碰到的查询变update或delete还跟我正在查询的数据有关的话,这次我碰到的问题是,我查询的数据,压根儿和最终变成的update语句不沾边。

        在此之前百度的时候,看到一篇文章,提到持久化的问题,当时也没太在意具体说的是什么,但这次碰到的问题给我折腾的够呛,死活都找不出来原因。于是只好跟踪代码,当跟踪到org.hibernate.jpa.internal.QueryImpl中的beforeQuery函数中时,终于发现了问题所在:

private void beforeQuery() {
		final org.hibernate.Query query = getHibernateQuery();
		if ( !SQLQuery.class.isInstance( query ) ) {
			// this need only exists for native SQL queries, not JPQL or Criteria queries (both of which do
			// partial auto flushing already).
			return;
		}

		final SQLQuery sqlQuery = (SQLQuery) query;
		if ( sqlQuery.getSynchronizedQuerySpaces() != null && !sqlQuery.getSynchronizedQuerySpaces().isEmpty() ) {
			// The application defined query spaces on the Hibernate native SQLQuery which means the query will already
			// perform a partial flush according to the defined query spaces, no need to do a full flush.
			return;
		}

		// otherwise we need to flush.  the query itself is not required to execute in a transaction; if there is
		// no transaction, the flush would throw a TransactionRequiredException which would potentially break existing
		// apps, so we only do the flush if a transaction is in progress.
		if ( getEntityManager().isTransactionInProgress() ) {
			getEntityManager().flush();
		}
	}

这个函数里注解写的很明白,我的语句首先是nativeQuery,所以过滤掉第一个条件;第二个条件也不符合,就只能进第三个if,这里说的是“we only do the flush if a transaction is in progress”,既然只flush一个进行中的transaction,那我哪里有这个一个transaction呢?这时想起前面说持久化问题的文章,好像提到他解决的方案是把查询到的实体另行复制出来再改变其中的属性,受到启发,我也回看我在执行自己的查询语句前有没有查询出来实体度对其进行更改的,一查果然有,我先是查询出来一个实体,并对该实体某一属性赋值,然后执行的这个查询函数,再然后才又执行保存实体的动作。OK,我把对实体某一属性赋值这个操作放在查询之后,亦即查询出来的实体不做 更改,发现一切正常了。

<think>好的,用户的问题是解决Maven项目中缺少org.apache.shiro:shiro-core:1.1.0依赖项的问题。首先,我需要回忆Maven依赖解析的常见原因和解决方法。用户提到的错误可能是依赖未正确配置、仓库不可达、版本不存在或本地仓库损坏。 首先,检查pom.xml中的依赖声明是否正确。正确的groupId、artifactId和版本号是关键。用户提到的是1.1.0,但根据引用[5],Shiro 1.4.0存在,可能用户需要确认版本是否可用。可能需要建议用户检查仓库中是否存在该版本,比如去Maven中央仓库搜索。 接下来,网络问题可能导致无法下载依赖。需要建议用户检查网络连接,确认Maven的settings.xml中的镜像配置是否正确,或者尝试手动访问仓库URL。如果公司有内部仓库,可能需要配置镜像。 如果本地仓库损坏,可能需要清除相关依赖并重新下载。可以指导用户删除.m2/repository下的对应目录,然后执行mvn clean install。 另外,多模块项目中的父模块版本问题也可能导致依赖解析失败,如引用[4]中的情况。需要检查父项目的版本号是否一致,特别是使用变量时是否正确定义。 还有可能依赖被排除,如引用[3]中的例子,需要检查是否有其他依赖排除了shiro-core。如果存在这种情况,需要移除exclusion。 最后,如果所有方法都无效,可能需要手动安装依赖,或者升级到更高版本,如引用[5]中的1.4.0,并测试兼容性。需要提醒用户注意版本升级可能带来的变化。 总结步骤应该是逐步排查配置、网络、仓库、版本等问题,确保用户能一步步解决问题。</think>### 解决Maven项目中缺少`org.apache.shiro:shiro-core:1.1.0`依赖的步骤 #### 1. **验证依赖配置** - 在`pom.xml`中确认依赖声明是否完整且无拼写错误: ```xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.1.0</version> </dependency> ``` - **注意**:通过[Maven中央仓库查询](https://search.maven.org/)确认该版本是否存在。若版本已过时或不存在,需升级至可用版本(如`1.4.0`)[^5]。 #### 2. **检查Maven仓库配置** - 确保`settings.xml`中未配置错误的镜像仓库。例如: ```xml <mirror> <id>central</id> <url>https://repo.maven.apache.org/maven2/</url> <mirrorOf>central</mirrorOf> </mirror> ``` - 若使用私服(如Nexus),需检查私服是否同步了该依赖。 #### 3. **清理本地仓库缓存** - 删除本地Maven仓库中损坏的依赖目录: ```bash rm -rf ~/.m2/repository/org/apache/shiro/shiro-core/1.1.0 ``` - 重新执行`mvn clean install`触发依赖下载。 #### 4. **解决多模块项目版本冲突** - 若项目为多模块结构,确保父模块中定义的版本变量(如`<shiro.version>1.1.0</shiro.version>`)与子模块引用一致[^4]。 - 示例父模块配置: ```xml <properties> <shiro.version>1.1.0</shiro.version> </properties> ``` #### 5. **排查依赖排除问题** - 检查其他依赖是否排除了`shiro-core`,例如: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <exclusions> <!-- 若存在对shiro-core的排除,需移除 --> <exclusion> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> </exclusion> </exclusions> </dependency> ``` 移除相关`<exclusion>`标签后重新构建[^3]。 #### 6. **手动安装依赖(备用方案)** - 若仓库不可用,可手动下载JAR文件并安装到本地仓库: ```bash mvn install:install-file -DgroupId=org.apache.shiro -DartifactId=shiro-core -Dversion=1.1.0 -Dfile=shiro-core-1.1.0.jar -Dpackaging=jar ``` #### 7. **升级Shiro版本** - 若`1.1.0`版本已废弃,建议升级至稳定版本(如`1.4.0`): ```xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> ``` 需同步更新相关代码以兼容新版本API[^5]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值