为了账号安全,请及时绑定邮箱和手机立即绑定

我怎么知道准备好的语句是否被缓存?

我怎么知道准备好的语句是否被缓存?

aluckdog 2022-12-15 15:03:20
工具栏菜单在片段中膨胀,但随后被清除。首次创建(或旋转)活动时,工具栏菜单会在片段中正确膨胀,但在显示之前会被清除。我在我的片段中设置了工具栏菜单onActivityCreated,它在活动中保持设置状态onResume。我发现的下一个电话是在onCreateOptionsMenu活动中,但此时toolbar.getMenu().size() = 0介于两者之间的某处onResume,onCreateOptionsMenu工具栏菜单正在重置。编辑:我不确定重现它需要什么,但这里是相关代码的全部(?)。活动:    private Toolbar toolbar;    private DrawerLayout drawer;    private ActionBarDrawerToggle toggle;    private FloatingActionButton fab;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.drawer_main);        toolbar = findViewById(R.id.toolbar);        setSupportActionBar(toolbar);        fab = findViewById(R.id.main_fab);        drawer = findViewById(R.id.drawer_layout);        toggle = new ActionBarDrawerToggle(this, drawer,toolbar,R.string.nav_drawer_open,R.string.nav_drawer_close);        drawer.addDrawerListener(toggle);        NavigationView navigationView = findViewById(R.id.nav_view);        navigationView.setNavigationItemSelectedListener(this);        if (savedInstanceState == null) {            showFragment(ScheduleFragment.newInstance());        }    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        if(toggle.onOptionsItemSelected(item)) {            return true;        }        return super.onOptionsItemSelected(item);    }    @Override    protected void onPostCreate(Bundle savedInstanceState) {        CharSequence retainTitle = toolbar.getTitle();        super.onPostCreate(savedInstanceState);        toggle.syncState();        toolbar.setTitle(retainTitle);    }
查看完整描述

3 回答

?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

HikariCP 实际上不支持PreparedStatement 缓存

其他人提供 PreparedStatement 缓存。HikariCP 没有。为什么?

它被认为是错误的实施

在池层使用语句缓存是一种反模式,与驱动程序提供的缓存相比,会对您的应用程序性能产生负面影响。

解释:

在连接池层 PreparedStatements 只能缓存每个连接。如果您的应用程序有 250 个经常执行的查询和一个包含 20 个连接的池,您要求您的数据库保留 5000 个查询执行计划——同样,池必须缓存这么多 PreparedStatements 及其相关的对象图。

大多数主要的数据库 JDBC 驱动程序已经有一个可以配置的语句缓存,包括 PostgreSQL、Oracle、Derby、MySQL、DB2 等等。JDBC 驱动程序处于利用数据库特定功能的独特位置,几乎所有缓存实现都能够跨连接共享执行计划。这意味着您的 250 个经常执行的查询会在数据库中产生恰好 250 个执行计划,而不是内存中的 5000 个语句和相关的执行计划。聪明的实现甚至不会在驱动程序级别的内存中保留 PreparedStatement 对象,而只是将新实例附加到现有计划 ID。

如果你接受它,你不应该尝试\期望缓存PreparedStatement

如果拒绝,可以使用C3P0作为连接池

关于hibernate中的二级缓存,大多没有在连接池中定义,而是使用相关的连接提供者:

HikariCP 现在有一个用于 Hibernate 4.x 的 ConnectionProvider,称为 HikariConnectionProvider

为了在 Hibernate 4.x 中使用 HikariConnectionProvider,将以下属性添加到您的 hibernate.properties 配置文件中:

hibernate.connection.provider_class=com.zaxxer.hikari.hibernate.HikariConnectionProvider

从 Hibernate 4.3.6 开始,有一个来自 Hibernate 的官方 ConnectionProvider 类,应该使用它来代替 HikariCP 实现。该类称为org.hibernate.hikaricp.internal.HikariCPConnectionProvider


查看完整回答
反对 回复 2022-12-15
?
侃侃无极

TA贡献2051条经验 获得超10个赞

正如 user7294900 所解释的,HikariCP 不缓存准备语句。它将此任务委托给驱动程序。


微软从 v6.3.0-preview 添加了准备好的语句缓存


JDBC 驱动程序的准备语句元数据缓存

它可以像这样激活:


connection.setStatementPoolingCacheSize(10)

connection.setDisableStatementPooling(false)


查看完整回答
反对 回复 2022-12-15
?
慕森王

TA贡献1777条经验 获得超3个赞

对于任何寻找 Oracle JDBC 的人,从链接中引用,


尽管 Oracle JDBC 驱动程序在设计时假设启用了隐式缓存,但默认情况下并未启用此功能。要在连接上启用隐式缓存,可以将相应 OracleConnection 对象的 implicitCachingEnabled 属性设置为 true,并将 statementCacheSize 属性设置为正整数


要在连接池上启用它,我们需要


connectionPoolObject.setMaxStatements(10);

如果这样做,将为池中的每个连接启用语句缓存


要验证缓存是否已启用,


  if (conn.getImplicitCachingEnabled())

       System.out.println("\nimplicit caching enabled");

  else

       System.out.println("\nimplicit caching disabled"); 

我们甚至可以在语句级别进行验证,


//Checking the creation state of the prepared statement

int creationState = stmt.creationState();

switch(creationState) {

 case 0:

 System.out.println("\nCreation state: new");

 break;

case 1:

 System.out.println("\nCreation state: from the implicit cache"); 

 break;

case 2:

 System.out.println("\nCreation state: from the explicit cache"); 

 break;

}

当该语句第一次在连接 C1 上执行时,情况 1 将为真,如果同一语句在同一连接 C1 上再次执行,则情况 2 将为真。


查看完整回答
反对 回复 2022-12-15
  • 3 回答
  • 0 关注
  • 77 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信