mybatis缓存配置 缓存 数据变了怎么办

1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
MyBatis技术分享
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口当其外部的数据库连接甚至是数据库管理系统,对数据库进行了更改,iBatis(MyBatis)的缓存如果没有过期,是不会对数据库的修改做出相应的?这一点有什么好的解决方案?
再简单的描述一下(假设数据库系统为MySQL),例如有一个Java的应用持久层框架是使用iBatis(MyBatis)有一个每个500ms(毫秒)调用一次对数据库中ID为100的记录进行 select 操作,由于缓存的时间很长,此时有一个外部程序,假设此程序为一个C/C++程序通过mysql C API 连接到当前数据库(和java应用程序同一个数据库)它将ID为100的记录删除了。然而此时java应用中每个500ms对此记录进行select 操作依然有效!这个很郁闷,iBatis(MyBatis)的缓存有什么选项能够对外部数据库连接对记录进行修改或者删除能让iBatis(MyBatis)主动清除缓存?
采纳的答案
MyBatis中没有这个机制。
MyBatis二级缓存工作原理是所有针对数据源的CRUD操作都先经过
缓存处理,对于查询操作,如果能正好命中缓存中的数据,直接从
缓存中返回,减少和数据库的IO操作来提高性能,否则查询数据库
将数据加入缓存再返回。对于增删改,修改数据库以后在返回之前
同时修改缓存。
如果从外部不经过缓存直接修改数据,那么肯定缓存中的数据和
真实数据会不一致。
如果一定有这个需求,可以在系统中对外提供数据增、删、改的服务;
或者当外部修改数据后,向系统发送通知,系统再刷新缓存。
你这个得改变缓存策略,既然有外部影响,不能光靠mybatis自身的缓存了,你自己可以实现应用一层的缓存比较好点,也不难,无非就是存对象取对象了。
缓存本只改用于那些较少更改或者脏数据对应用影响不大的地方
如果需要数据库中实时的数据,那么就不适合用缓存了
已解决问题
未解决问题【mybatis】多次查询缓存的有关问题_数据持久化(6)之Using CoreData with MagicalRecord_机房收费系统汇总(二)-玩转DataGridView__脚本百事通
稍等,加载中……
^_^请注意,有可能下面的2篇文章才是您想要的内容:
【mybatis】多次查询缓存的有关问题
数据持久化(6)之Using CoreData with MagicalRecord
机房收费系统汇总(二)-玩转DataGridView
【mybatis】多次查询缓存的有关问题
【mybatis】多次查询缓存的问题
最近在使用mybatis的过程中,发现一个问题。如果在同一个事物中,多次同一个查询sql在mybatis的执行过程中,只会查询一次数据库,后几次所返回的对象是mybatis在在内部做了缓存。
Property property = this.findByPropertyId("123");
property.setPropertyId(null);;
property = this.findByPropertyId("123");
System.out.println(property.getPropertyId());
以上的代码,打印的结果为 null , 但是我们所期望的可能是 123 , 我不知道这是mybatis的一个bug还是故意这样去设计的.mybatis在执行查询语句的时候,会在本地做一份缓存信息.在BaseExecutor类中:
private &E& List&E& queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
localCache.putObject(key, EXECUTION_PLACEHOLDER);
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
可以看到在queryFromDatabase方法中,查询数据库返回结果之后,mybatis编制了一个cachekey的对象,作为key,返回结果作为value,放入了缓存当中(这个地方没有使用拷贝的函数,所以只要外部修改了值,内部缓存中的值信息也会被修改)
之后再下次查询的时候,会依据一个判断,是否需要执行缓存信息,同样是在BaseExecutor类中.
@SuppressWarnings("unchecked")
public &E& List&E& query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) throw new ExecutorException("Executor was closed.");
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
queryStack++;
list = resultHandler == null ? (List&E&) localCache.getObject(key) :
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
} finally {
queryStack--;
if (queryStack == 0) {
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
deferredLoads.clear(); // issue #601
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
clearLocalCache(); // issue #482
看到mybatis判断了 ms.isFlushCacheRequired() 的返回数据,如果为 true 会执行 clearLocalCache 方法,清空缓存信息。如果缓存中获取不到的话,才会继续去查询数据库。可以从
list = resultHandler == null ? (List&E&) localCache.getObject(key) : 代码中看出。
所以当第一次查询放入缓存之后,在外部修改了任何一个值之后,mybatis内部缓存的值也会被修改,而且下次查询不会查询数据库,直接返回缓存中被修改过的值
ms.isFlushCacheRequired() 这段代码的判断是基于了一个MappedStatement 类中的flushCacheRequired 的属性做判断的。flushCacheRequired
变量可以通过注解的方式和xml的方式来配置
1.注解:注解的方式是通过 @Options 注解中 flushCache 的配置
2.配置文件:xml中每一个select 都可以设置 flushCache 的属性
flushCache 设置成true之后,本sql的每次查询都会清空缓存后在执行。
数据持久化(6)之Using CoreData with MagicalRecord
数据持久化(六)之Using CoreData with MagicalRecord
第五节里面,我介绍了CoreData的配置和基本的增删改查,可能很多人会觉得用它真繁琐.这里,我再介绍网上大神对它进行了人性化封装的第三方MagicalRecord,正如FMDB对sqlite进行了封装一样,MagicalRecord让你觉得用CoreData很方便.
@基本配置:
1.下载MagicalRecord,将里面的MagicalRecord文件夹拖入你的工程
2.确定你创建的工程没有勾选"Use Core Data"
3.导入CoreData.frame框架
4.在.pch文件中引入头文件"CoreData+MagicalRecord.h"(只能,必须在这里引用)
@具体操作:
1.初始化(在didFinishLaunchingWithOptions中)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
HMTRootViewController *rootVC = [[HMTRootViewController alloc] init];
self.window.rootViewController = rootVC;
[MagicalRecord setupCoreDataStackWithStoreNamed:@"MT.sqlite"];
[self.window makeKeyAndVisible];
return YES;
- (void)applicationWillTerminate:(UIApplication *)application
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[MagicalRecord cleanUp];
2.创建一个Model做测试,创建一个Person的Entity
3.增删改查具体操作
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
初始化一个Person对象
这里要注意:默认,xcdatamodeld实体描述表名(name)和类名(class)必须保持一致
如果name和class不一致,实现MagicalRecord_MOGenerator协议中得entityName方法来改变
@implementation NSManagedObject (MagicalRecord)
+ (NSString *) MR_entityN
NSString *entityN
if ([self respondsToSelector:@selector(entityName)])
entityName = [self performSelector:@selector(entityName)];
if ([entityName length] == 0) {
entityName = NSStringFromClass(self);
return entityN
Person *person = [Person MR_createEntity];
person.name = @"HMT";
person.sex = @"男";
person.age = @25;
- (void)addDataOperation{
// 文档解释:For any entities to actually be saved / updated / deleted on disk call following method(增加,更新,删除 都要用这个方法来保存数据)
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];;
- (void)selectDataOperation{
find数据库中所有的人
NSArray *peoples = [Person MR_findAll];
find数据库中第一条记录
Person *firPerson = [Person MR_findFirst];
find数据库中所有name属性为"HMT"的人并按照年龄age排序
NSArray *otherPeoples = [Person MR_findByAttribute:@"name" withValue:@"HMT" andOrderBy:@"age" ascending:YES];
- (void)upDataOperation{
选定要修改的人
NSArray *persons = [Person MR_findByAttribute:@"name" withValue:@"HMT"];
for (Person *person in persons) {
person.name = @"WDQ";
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
- (void)deleteDataOperation{
delete数据库中所有人
[Person MR_truncateAll];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
根据条件delete特定的某个人
NSArray *persons = [Person MR_findByAttribute:@"name" withValue:@"HMT"];
for (Person *person in persons) {
[person MR_deleteEntity];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
4.额外配置(取消前缀名和不打印日志信息)
//If you want to omit the "MR_" prefix to all MagicalRecord realted method calls define following before importing the MagicalRecord header
#define MR_SHORTHAND
//Turn off MagicalRecord logging, again by defining following before header import
#define MR_ENABLE_ACTIVE_RECORD_LOGGING 0
@以上只是一些基本操作,其他可以自己去查看头文件
机房收费系统汇总(二)-玩转DataGridView
机房收费系统集锦(二)--玩转DataGridView
做到现在了,敲代码的快感又如约而至了。不得不说,敲代码实在是一件富有激情的事儿。
好了,今天谈谈与数据显示有关的控件DataGridView吧。
其实在VB6中,大家对它已经有了一定的了解了,相信当时对于这个控件使用的纠结感觉已经不复存在了吧。在vb.net中,它的使用变得更加简单了。
下面以机房中的“查询充值记录”窗体为例,详细介绍一下gvw的“变形记”。
在Entity层中,只定义了CardNo这一个变量,就不在具体写出来了。
DLL层,处理数据,查询数据库里的充值信息
Public Function SelectChargeInfo(ByVal chargeInfo As Entity.frmChargeRecordEntity) As DataTable
Dim connStr As String = "Server=Yang-PC;Database=ReCUser ID=Password=123456"
Dim conn As New SqlConnection(connStr)
Dim cmd As New SqlCommand
cmd.Connection = conn
'T-SQL语句,选择需要显示的数据列
mandText = "Select T_ReCharge.cardNo,T_ReCharge.UserID,T_ReCharge.addMoney,T_ReCharge.Date,T_ReCharge.Time From T_ReCharge Where cardNo=@CardNo"
cmd.Parameters.Add(New SqlParameter("@CardNo", chargeInfo.CardNo))
'给sql添加参数
mandType = CommandType.Text
conn.Open()
'打开数据库
Dim dataAdapter As New SqlDataAdapter
'实例化数据适配器SqlDataAdapter
Dim dst As New DataSet
'实例化数据集DataSet
Dim dt As New DataTable
'实例化数据表DataTable
dataAdapter.SelectCommand = cmd
'执行在数据源中选中的记录
dataAdapter.Fill(dst, "chargeInfo")
'对数据集进行填充
dt = dst.Tables("chargeInfo")
'形成临时数据表
SqlHelper.sqlHelp.CloseDB()
'关闭数据库
End Function
BLL层,简单调用D层函数
Public Function SelectCharge(ByVal ChargeInfo As Entity.frmChargeRecordEntity) As DataTable
Dim ChargeInfoDal As New DAL.frmChargeRecordDal
'Dim ChargeInfoEntity As New Entity.frmChargeRecordEntity
Dim dt As New DataTable
dt = ChargeInfoDal.SelectChargeInfo(ChargeInfo)
'执行D层的查询
End Function
UI层,对控件进行一些外观上的处理和加工
Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
ChargeInfoEntity.CardNo = txtCardNo.Text.Trim
' 设置用户不能手动给 DataGridView 添加新行
gvwChargeRecord.AllowUserToAddRows = False
If MSetText.TextSet(txtCardNo) = True Then
'此方法是设置文本框不为空等条件的自定义函数
'执行BLL层下的查询充值记录
gvwChargeRecord.DataSource = ChargeInfoBll.SelectCharge(ChargeInfoEntity)
'更改列的字段名
gvwChargeRecord.Columns(0).HeaderText = "卡号"
gvwChargeRecord.Columns(1).HeaderText = "充值教师"
gvwChargeRecord.Columns(2).HeaderText = "充值金额"
gvwChargeRecord.Columns(3).HeaderText = "充值日期"
gvwChargeRecord.Columns(4).HeaderText = "充值时间"
If gvwChargeRecord.Rows.Count = 0 Then
MsgBox("卡号不存在")
txtCardNo.Focus()
gvwChargeRecord.AutoGenerateColumns = True
'自动添加新列
gvwChargeRecord.ReadOnly = True
'所有的单元格设为只读,防止修改
Catch ex As Exception
MessageBox.Show(ex.ToString())
这是一篇功能型博客,一些其他的涉及到的使用方法和注意事项还会在以后总结出来,现在还是一篇“板砖之作”。
这就是我目前对这个控件使用的理解,大家如果对代码有什么好的意见,欢迎提出!
如果您想提高自己的技术水平,欢迎加入本站官方1号QQ群:&&,&&2号QQ群:,在群里结识技术精英和交流技术^_^
本站联系邮箱:

我要回帖

更多关于 mybatis一级缓存 的文章

 

随机推荐