请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

9-23 老师为什么没有遇到事务的问题

这是同意好友申请的方法A

@Transactional
    public ServerResponse acceptFriendRequest(Long acceptUserId, Long sendUserId) {
        // 通过好友请求
        // 1. 保存好友
        saveFriend(acceptUserId, sendUserId);
        // 2. 逆向保存好友
        saveFriend(sendUserId, acceptUserId);
        // 3. 删除申请好友记录
        deleteFriendRequest(acceptUserId, sendUserId);

        // 使用websocket主动推送消息到请求发起者, 更新他的通讯录
        Channel sendChannel = UserChannelRel.get(sendUserId);
        if(sendChannel != null) {
            DataContent dataContent = new DataContent();
            dataContent.setAction(MsgActionEnum.PULL_FRIEND.getType());
            sendChannel.writeAndFlush(new TextWebSocketFrame(JsonUtil.obj2String(dataContent)));
        }
        return ServerResponse.createBySuccess("添加好友成功");
    }

这是获得好友的方法B

    public ServerResponse<List<MyFriendVO>> queryMyFriends(Long userId) {
        Integer count = userRepository.countById(userId);
        if(count == 0) {
            return ServerResponse.createByError("该用户不存在");
        }
        return ServerResponse.createBySuccess(userRepository.queryMyFriends(userId));
    }

我们之前在添加通讯录好友的方法中因为是要双向添加好友并且删除申请记录的,三个数据库操作的service层我们带上了事务.
现在我遇到一个问题, 就是在这个事务方法中通过socket通知客户端去拉取最新的好友. 但每次socket一通知,客户端去服务端拉取数据,都没有获得最新的数据.试了好多次都是这样.

一分析下来只有可能是A方法事务还没有提交, 然后B方法直接去获取最新数据导致的
(这里还有个嵌套的小问题, 从socket通知客户端, 到客户端发起ajax请求到服务端怎么着都有个十几毫秒吧, 这么长的时间难道还不够A方法的事务提交吗 希望老师也能解答一下这个问题)

现在我有两个方法去解决这个问题,
一是客户端在收到socket通知后再延迟1s去执行

function fetchContactList() {
	setTimeout(() => {
		console.log("去请求了")
		var user = app.getUserGlobalInfo();
		
		console.log("这个是去获取好友的接口")
		console.log(app.serverUrl + "/client/user/myFriends?userId=" + user.id)
		
		mui.ajax(app.serverUrl + "/client/user/myFriends?userId=" + user.id,{
			data:{},
			dataType:'json',//服务器返回json格式数据
			type:'post',//HTTP请求类型
			timeout:100000,//超时时间设置为10秒;
			headers:{'Content-Type':'application/json'},	              
			success:function(data){
		
				console.log("这个是去请求的返回值", JSON.stringify(data))
				if (data.code == 0) {
					var contactList = data.data;
					app.setContactList(contactList);
				}
			}
		});
	}, 1000)
}

二是将B方法的事务隔离级别设置为可读未提交

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public ServerResponse<List<MyFriendVO>> queryMyFriends(Long userId) {
    Integer count = userRepository.countById(userId);
    if(count == 0) {
        return ServerResponse.createByError("该用户不存在");
    }
    return ServerResponse.createBySuccess(userRepository.queryMyFriends(userId));
}

我自己试过了, 这两种方法都能达到效果, 但是都不够优雅.
所以请问老师视频中没有遇到跟我一样的问题呢, 还有怎样才能确保A事务提交之后, B事务再开始请求呢?

正在回答 回答被采纳积分+3

2回答

风间影月 2019-03-29 09:56:11

https://img1.sycdn.imooc.com//szimg/5c9d7b390001a6e215010721.jpg
加群参考下图

0 回复 有任何疑惑可以回复我~
风间影月 2019-03-29 09:19:41

事务提交后,数据库查看有新的值吗?之前有个同学和你一模一样的问题,他是mybatis没有配置好的缘故,就是事务无法自动提交

0 回复 有任何疑惑可以回复我~
  • 提问者 学东西要快 #1
    老师我用的是jpa没有用mybatis  老师你这一问我也不知道事务是什么时候提交的诶 直观上理解应该是B方法执行完之后自动提交的
    回复 有任何疑惑可以回复我~ 2019-03-29 09:25:47
  • 按理说如果数据没有入库去查询,也可以拿到缓存数据的,你的jpa我推测是事务配置问题
    回复 有任何疑惑可以回复我~ 2019-03-29 09:29:38
  • 提问者 学东西要快 #3
    还有老师这事务应该是提交了的 因为客户端延迟1s就能生效了呀
    回复 有任何疑惑可以回复我~ 2019-03-29 09:30:50
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信