国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站做鏈輪會被懲罰嗎公司網(wǎng)站推廣方法

網(wǎng)站做鏈輪會被懲罰嗎,公司網(wǎng)站推廣方法,建設(shè)局網(wǎng)站港府名都,做電商網(wǎng)站公司簡介記Mybaits緩存踩的坑 1.問題提出 最近開發(fā)一個記錄操作前后修改內(nèi)容的功能,獲取修改前數(shù)據(jù)比較簡單,直接從數(shù)據(jù)庫獲取,記錄修改后的功能也比較簡單,直接將用戶修改的內(nèi)容封裝成po對象,然后兩個比對就可以了&#xff…

記Mybaits緩存踩的坑

1.問題提出

最近開發(fā)一個記錄操作前后修改內(nèi)容的功能,獲取修改前數(shù)據(jù)比較簡單,直接從數(shù)據(jù)庫獲取,記錄修改后的功能也比較簡單,直接將用戶修改的內(nèi)容封裝成po對象,然后兩個比對就可以了,問題就出在這。

2.場景復(fù)現(xiàn)

下面是出現(xiàn)問題的代碼,簡化版(操作分為用戶端和管理端):

用戶端

public class UserServiceImpl{@Autowiredprivate IUserDao userDao;@Autowiredprivate IUserLogDao dao;@Autowiredprivate StreamAction action;@Override@Transactionalpublic void modifyUser(UserDto dto){Long id = dto.getUserId;//修改前的beanUserBean beforeBean = userDao.queryUser(id);//修改后的beanBeanUtils.copyProperties(dto,beforeBean);//更新和用戶有關(guān)的內(nèi)容//....用戶信息填充 UserLogBean userLogBean//這里需要修改和用戶關(guān)聯(lián)的記錄,所以插入一次userDao.insert(userLogBean);//用戶端操作流action.request(beforeBean);}
}
  • StreamAction.request
@Override
@Transactional
public void request(UserBean userBean){/*** 獲取數(shù)據(jù)庫原內(nèi)容*/UserBean afterBean = userDao.queryUser(id);//比對返回修改內(nèi)容ModifyBean bean = modify(userBean,afterBean);//...其他 業(yè)務(wù)//插入修改后的內(nèi)容userBeanModifyDao.insert(bean);
}

此時去查看數(shù)據(jù)內(nèi)添加的內(nèi)容,可以看到,修改的部分被正確的比對出來了。

管理端

public class UserServiceImpl{@Autowiredprivate IUserDao userDao;@Autowiredprivate IUserLogDao dao;@Autowiredprivate StreamActionManager action;@Override@Transactionalpublic void modifyUser(UserDto dto){Long id = dto.getUserId;//修改前的beanUserBean beforeBean = userDao.queryUser(id);//修改后的beanBeanUtils.copyProperties(dto,beforeBean);//更新和用戶有關(guān)的內(nèi)容//....用戶信息填充 UserLogBean userLogBean//管理端操作流action.request(beforeBean);}
}
  • StreamActionManager.request
@Override
@Transactional
public void request(UserBean userBean){/***   獲取數(shù)據(jù)庫原內(nèi)容*/UserBean afterBean = userDao.queryUser(id);//比對返回修改內(nèi)容ModifyBean bean = modify(userBean,afterBean);//...其他 業(yè)務(wù)//插入修改后的內(nèi)容userBeanModifyDao.insert(bean);
}

此時我們?nèi)?shù)據(jù)庫查看內(nèi)容,你就驚奇發(fā)現(xiàn)并沒有見到修改的內(nèi)容。不對啊,我們確實(shí)已經(jīng)修改過了,那為什么數(shù)據(jù)庫里不顯示呢?

3.發(fā)現(xiàn)問題

帶著疑問,我們很容易的想到,是不是兩個對象內(nèi)容一模一樣?帶著疑問,我們嘗試著打印一下用戶端和管理端,在進(jìn)行比對前的兩個對象內(nèi)容:

public void request(UserBean userBean){/*** 獲取數(shù)據(jù)庫原內(nèi)容*/UserBean afterBean = userDao.queryUser(id);System.out.println(userBean);  System.out.println(afterBean); //比對返回修改內(nèi)容ModifyBean bean = modify(userBean,afterBean);//......
}

用戶端

我們在比對修改內(nèi)容前打印兩個bean,結(jié)果如下:

cn.example.core.core.bean.UserBean@5e5a2b74
cn.example.core.core.bean.UserBean@5e5a2b75

兩個bean不是同一個對象,符合我們的預(yù)期,所以用戶端正確入庫。

我們再來看管理端

管理端

管理端執(zhí)行結(jié)果

cn.example.core.core.bean.UserBean@5e5a2b77
cn.example.core.core.bean.UserBean@5e5a2b77

!!!oi!!!,我們驚奇的發(fā)現(xiàn),這兩個對象是一樣的,那就奇了怪了,用戶端和管理端業(yè)務(wù)代碼甚至基本都一樣的,為什么會造成這個原因呢?我們再輸出這兩個對象的內(nèi)容

System.out.println(userBean.toString());  
System.out.println(afterBean.toString());

很驚奇的是,這兩個對象內(nèi)容都是修改過的內(nèi)容,也就是service內(nèi)通過BeanUtils屬性賦值過的內(nèi)容,那我們mysql里的內(nèi)容去哪了??我們明明還沒更新啊!我們趕緊去數(shù)據(jù)庫看一眼,發(fā)現(xiàn)數(shù)據(jù)庫里并沒更新。數(shù)據(jù)庫里內(nèi)容沒更新,業(yè)務(wù)里的bean已經(jīng)被更新過了,這是為什么?

4.排查問題

我們找到出現(xiàn)問題的原因了,是因?yàn)楣芾矶藘蓚€對象一樣。那為什么會一樣呢?

我們在業(yè)務(wù)邏輯里很容易想到類似的場景,比如我們在使用redis的時候,當(dāng)redis內(nèi)有數(shù)據(jù)時,我們希望走redis返回結(jié)果而不是走數(shù)據(jù)庫,以提高查詢性能,那會不會兩個對象一樣也是走了緩存呢?我們通過查詢數(shù)據(jù)庫我們知道,mysql的查詢也會存在緩存,但是按道理來說,我們最后的結(jié)果應(yīng)該是mysql的內(nèi)容,應(yīng)該不會是后面的內(nèi)容。所以只有一種情況,是mybaits的緩存。

5.尋找答案

我們已經(jīng)確定了是mybaits的緩存導(dǎo)致的問題,但是為什么管理端和用戶端還不一樣呢?為什么用戶端就沒有這個問題呢?

我們百度之后發(fā)現(xiàn),mybaits有一、二級緩存之分,二級緩存默認(rèn)不開啟。

哎會不會是用戶端的緩存過期了?因?yàn)橛脩舳说挠幸粋€插入其他表的操作,肯定比管理端慢,對對一定是這個問題,好我們?nèi)フ叶饶?#xff0c;度娘說緩存沒有過期時間。好好好這樣玩,好好好。

那么問題是什么?我們已經(jīng)確定不是過期時間的問題了,那我們現(xiàn)在想的就是緩存過期,也就是緩存失效了,我們換個方法去查找內(nèi)容,“mybatis緩存失效的原因”,我們找到以下結(jié)果:

1.不在同一個sqlSession中
2.如果是增刪改操作,程序會clear緩存。
3.一級緩存未開啟
4.手動清空緩存數(shù)據(jù),調(diào)用sqlsession.clearCache().
5.更改查詢條件

我們一點(diǎn)點(diǎn)往下看:

  1. 不在同一個sqlSession中

同一個事務(wù)內(nèi)會復(fù)用同一個sqlSession。

具體我們查看控制臺,可以看到第一個sql執(zhí)行之前,會有一句話

Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3663af34]

在之后的sql執(zhí)行時會有一句話

Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3663af34] from current transaction

都是同一個sqlSession

我們業(yè)務(wù)層面的代碼是在同一個事務(wù)里,因?yàn)闆]有設(shè)置事物傳播機(jī)制,雖然有兩個事物注解,但是最后都在同一個事務(wù)那,可以用

String txName = TransactionSynchronizationManager.getCurrentTransactionName();

查看,會發(fā)現(xiàn)事務(wù)沒有失效且都在一個事物內(nèi),顯然不是這個原因。

  1. 如果是增刪改操作,程序會clear緩存。

我們用戶端涉及的增刪改是另外一張表的,排除

  1. 一級緩存未開啟

顯然開啟了,不然不會有這篇博客

4、5不用看了,都不符合

我們分析完了,仍然沒找到原因。那么問題到底在哪呢?

目前最有可能的就是2,但是我們明明更改的是其他表啊,那么不妨,我們就試試改其他表。

@Test
@Transactional  //這里的事務(wù)一定要加,mybatis的緩存存在條件就是需要有事務(wù),否則你查詢會發(fā)現(xiàn)兩個對象怎么樣都不會相同
public void test(){UserBean beforeBean = userDao.queryUser(id);//更新userLogDao.update("1","1");UserBean afterBean = userDao.queryUser(id);System.out.println(beforeBean);  System.out.println(afterBean); }

哎,神奇,兩個對象不一樣了,緩存失效了!所以問題就在這,所以這就是造成這個bug的原因,知道了問題,那我們就開始做解決方案

6.解決方案

解決方案有一下幾種:

  • 關(guān)閉mybatis一級緩存,無法關(guān)閉,只能修改狀態(tài)
mybatis:configuration:cache-enabled: false #禁用二級緩存local-cache-scope: statement #一級緩存指定為statement級別 默認(rèn)為session級別
  • 使用不同的對象傳遞

在傳遞前后bean的時候,用其他的bean賦值傳遞。

  • 使用不同的查詢方式,拼接條件等
  • 使用不同的事物隔離級別,sqlSession是依賴于mysql的事物,所以如果數(shù)據(jù)庫不支持事物那么Spring的事物 也不會生效。我們可以使用不同的事物隔離級別,以創(chuàng)建不同的sqlSessio,此時就不存在bean不同的問題:
  @Override@Transactionalpublic void modifyUser(UserDto dto){Long id = dto.getUserId;//修改前的beanUserBean beforeBean = userDao.queryUser(id);//修改后的beanBeanUtils.copyProperties(dto,beforeBean);//更新和用戶有關(guān)的內(nèi)容//....用戶信息填充 UserLogBean userLogBean//管理端操作流action.request(beforeBean);}//另外一個類的request方法@Override@Transactional(propagation = Propagation.REQUIRES_NEW)public void request(UserBean userBean){/***   獲取數(shù)據(jù)庫原內(nèi)容*/UserBean afterBean = userDao.queryUser(id);//比對返回修改內(nèi)容ModifyBean bean = modify(userBean,afterBean);//...其他 業(yè)務(wù)//插入修改后的內(nèi)容userBeanModifyDao.insert(bean);}

使用不同的事物傳播機(jī)制,我們可以看到控制臺創(chuàng)建了兩個sqlSession:

Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7488c183]//....
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4797023d]//再次比較兩個bean
cn.example.core.core.bean.UserBean@4b86a656
cn.example.core.core.bean.UserBean@4c3c31a5

到此為止,我們的問題就解決了。

http://m.aloenet.com.cn/news/35112.html

相關(guān)文章:

  • wordpress 換域名 全站301重定向百度熱搜榜小說排名
  • png圖片可以做網(wǎng)站圖標(biāo)嗎建設(shè)網(wǎng)站需要多少錢
  • 河源城鄉(xiāng)規(guī)劃建設(shè)局網(wǎng)站軟文新聞發(fā)布網(wǎng)站
  • 動態(tài)網(wǎng)站開發(fā)參考資料google建站推廣
  • 自己建的網(wǎng)站可以用筆記本做服務(wù)器嗎sem專員
  • 泗洪網(wǎng)站設(shè)計公司ip域名查詢網(wǎng)站入口
  • 抖音代運(yùn)營排名seo公司排行
  • 主流網(wǎng)站風(fēng)格精品成品網(wǎng)站入口
  • 網(wǎng)站開發(fā)實(shí)訓(xùn)報告參考文獻(xiàn)國內(nèi)真正的永久免費(fèi)建站
  • 免費(fèi)看電影的網(wǎng)站是什么快速收錄網(wǎng)
  • 怎樣做網(wǎng)站開發(fā)搜索優(yōu)化seo
  • 網(wǎng)站站長統(tǒng)計代碼百度風(fēng)云搜索榜
  • 蘇州專業(yè)做網(wǎng)站公司有哪些如何進(jìn)行電子商務(wù)網(wǎng)站推廣
  • 高端做網(wǎng)站做網(wǎng)站要多少錢
  • wordpress網(wǎng)站服務(wù)器深圳市seo點(diǎn)擊排名軟件價格
  • 河北通信建設(shè)有限公司網(wǎng)站搜索引擎優(yōu)化什么意思
  • 上海網(wǎng)站設(shè)計服務(wù)商長尾詞挖掘免費(fèi)工具
  • 網(wǎng)站開發(fā)論文需要寫什么windows優(yōu)化大師怎么使用
  • wordpress短視頻主題上海整站seo
  • 兼職做調(diào)查哪個網(wǎng)站好溫州seo公司
  • 成都 高端網(wǎng)站建設(shè)如何制作網(wǎng)頁最簡單的方法
  • 網(wǎng)站設(shè)計如何收費(fèi)上海專業(yè)網(wǎng)絡(luò)推廣公司
  • 公司網(wǎng)站自己可以做嗎外包項目接單平臺
  • 怎么添加網(wǎng)站百度網(wǎng)盤下載電腦版官方下載
  • 建商城網(wǎng)站如何去推廣一個app
  • 上海著名網(wǎng)站設(shè)計公司網(wǎng)絡(luò)營銷品牌
  • 微網(wǎng)站 微官網(wǎng)的區(qū)別嗎最近的新聞大事10條
  • 深色大氣網(wǎng)站模板電腦培訓(xùn)學(xué)校學(xué)費(fèi)多少
  • web網(wǎng)站開發(fā)的基本流程產(chǎn)品運(yùn)營方案
  • php網(wǎng)站怎么做測試工具上海網(wǎng)站建設(shè)開發(fā)