Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Infinispan中父子关系的类缓存数据库索引_Java_Caching_Infinispan - Fatal编程技术网

Java Infinispan中父子关系的类缓存数据库索引

Java Infinispan中父子关系的类缓存数据库索引,java,caching,infinispan,Java,Caching,Infinispan,我的应用程序运行在Wildfly 10.0.0服务器上。我将实体存储在数据库中,但为了提高性能,我决定使用Infinispan缓存(缓存旁模式)。 应用程序性能有所提高,但计算关系父子(Foo和SubFos)仍然存在问题: 这是实体代码: @Entity class Foo { Long id; } @Entity class SubFoo { Long id; Long fooId; } 这是服务代码: public class FooService {

我的应用程序运行在Wildfly 10.0.0服务器上。我将实体存储在数据库中,但为了提高性能,我决定使用Infinispan缓存(缓存旁模式)。 应用程序性能有所提高,但计算关系父子(Foo和SubFos)仍然存在问题:

这是实体代码:

@Entity
class Foo
{
      Long id;
}

@Entity
class SubFoo
{
      Long id;
      Long fooId;
}
这是服务代码:

public class FooService
{
    @Inject
    EntityManger em;

    @Inject
    Cache<Long, Foo> fooCache;

    @Inject
    Cache<Long, SubFoo> subFooCache;

    public void save(Foo foo)
    {
        em.save(foo);
        fooCache.put(foo.id, foo);
    }

    public void save(SubFoo subFoo)
    {
        em.save(subFoo);
        subFooCache.put(subFoo.id, subFoo);
    }

    public void remove ....

    public void update ....

    public Foo get(Long fooId)
    {
        return fooCache.get(fooId);
    }

    public SubFoo get(Long subFooId)
    {
        return subFooCache.get(subFooId);
    }


    public List<SubFoo> findSubFoo(Long fooId)
    {
        return subFooCache.values().stream().filter( subFoo -> subFoo.fooId == fooId ).collect( Collector.list() );
    }
}
公共类服务
{
@注入
全基因组;
@注入
缓存fooCache;
@注入
缓存子焦点;
公共作废保存(Foo-Foo)
{
em.save(foo);
fooCache.put(foo.id,foo);
}
公共作废保存(子文件夹子文件夹)
{
em.save(subfo);
subfocache.put(subFoo.id,subfo);
}
公共空间删除。。。。
公共无效更新。。。。
公共Foo-get(长fooId)
{
返回fooCache.get(fooId);
}
public子对象get(长子对象)
{
返回subfocache.get(子类);
}
公共列表findSubFoo(长fooId)
{
返回subfocache.values().stream().filter(subfo->subFoo.fooId==fooId.collect(Collector.list());
}
}
问题在于findSubFoo方法。每次都必须检查所有子OS集合。而且这种方法对应用程序性能仍然有很大的影响

infinispan是否可以模拟使用数据库索引或以其他方式解决该问题

方法1

我尝试使用TreeCache将列表存储为缓存值,并保持并发性和事务性支持。treeNode将FooId保持为节点根路径,将子类保持为叶子。 当请求数量较少时,这种方法还可以。在许多请求中,状态不一致,短状态不一致。似乎已经提交了Tx,并且刷新了一个缓存(对于实体子对象来说是正常的),但第二个缓存(foo2subFoo)尚未刷新。但在短时间内,一切正常,数据的一致性又恢复了

源代码:

具有生产者的缓存提供程序:

@ApplicationScoped
public class CacheProvider
{
    private EmbeddedCacheManager cacheManager;

    @PostConstruct
    public void init()
    {
        final GlobalConfiguration globalConfig =
            new GlobalConfigurationBuilder().nonClusteredDefault().globalJmxStatistics()
                .allowDuplicateDomains( true ).build();

        final Configuration entityDefaultConfig =
            new ConfigurationBuilder().transaction().transactionMode( TransactionMode.TRANSACTIONAL )
                .lockingMode( LockingMode.OPTIMISTIC )
                .eviction().strategy( EvictionStrategy.NONE ).build();

        final Configuration indexDefaultConfig = new ConfigurationBuilder()
            .transaction().transactionMode( TransactionMode.TRANSACTIONAL )
            .eviction().strategy( EvictionStrategy.NONE )
            .invocationBatching().enable()
            .build();

        cacheManager = new DefaultCacheManager( globalConfig  );

        cacheManager.defineConfiguration( "Foos", entityDefaultConfig );
        cacheManager.defineConfiguration( "SubFoos", entityDefaultConfig );
        cacheManager.defineConfiguration( "Foo2SubFoos", indexDefaultConfig );
    }

    @Produces
    public Cache<Long, Foo> createFooCache()
    {
        final Cache<Long, Foo> entityCache = cacheManager.getCache( "Foos" );
        return entityCache;
    }

    @Produces
    public Cache<Long, SubFoo> createSubFooCache()
    {
        final Cache<Long, SubFoo> entityCache = cacheManager.getCache( "SubFoos" );
        return entityCache;
    }

    @Produces
    public TreeCache<Long, Boolean> createFoo2SubFoos()
    {
        Cache<Long, Boolean> cache = cacheManager.getCache("Foo2SubFoos");

        final TreeCacheFactory treeCacheFactory = new TreeCacheFactory();
        final TreeCache<Long, Boolean> treeCache = treeCacheFactory.createTreeCache( cache );

        return treeCache;       
    }
}
@ApplicationScoped
公共类缓存提供程序
{
私有嵌入式cacheManager cacheManager;
@施工后
公共void init()
{
最终全局配置全局配置=
新的GlobalConfiguration Builder().nonClusteredDefault().globalJmxStatistics()
.allowDuplicateDomains(true).build();
最终配置entityDefaultConfig=
新建ConfigurationBuilder().transaction().transactionMode(transactionMode.TRANSACTIONAL)
.锁定模式(锁定模式.乐观)
.execution().strategy(executionstrategy.NONE).build();
最终配置indexDefaultConfig=new ConfigurationBuilder()
.transaction().transactionMode(transactionMode.TRANSACTIONAL)
.execution().strategy(executionstrategy.NONE)
.invocationBatching().enable()
.build();
cacheManager=新的DefaultCacheManager(globalConfig);
cacheManager.defineConfiguration(“Foos”,entityDefaultConfig);
cacheManager.defineConfiguration(“subfos”,entityDefaultConfig);
defineConfiguration(“Foo2SubFoos”,indexDefaultConfig);
}
@产生
公共缓存createFooCache()
{
最终缓存entityCache=cacheManager.getCache(“Foos”);
返回实体缓存;
}
@产生
公共缓存createSubfocache()
{
最终缓存entityCache=cacheManager.getCache(“子操作系统”);
返回实体缓存;
}
@产生
公共树缓存createFoo2SubFoos()
{
Cache Cache=cacheManager.getCache(“Foo2SubFoos”);
最终TreeCacheFactory TreeCacheFactory=新的TreeCacheFactory();
final TreeCache TreeCache=treeCacheFactory.createTreeCache(缓存);
返回树;
}
}
我还通过对TreeCache的支持扩展了我的FooService:当添加、删除或删除subFoo id时,foo2SubFoo缓存也会刷新

public class FooService
{
    @Inject
    EntityManger em;

    @Inject
    Cache<Long, Foo> fooCache;

    @Inject
    Cache<Long, SubFoo> subFooCache;

    @Inject
    TreeCache<Long, Boolean> foo2SubFoosCache;  


    public void save(Foo foo)
    {
        em.save(foo);
        fooCache.put(foo.id, foo);
    }

    public void save(SubFoo subFoo)
    {
        em.save(subFoo);
        subFooCache.put(subFoo.id, subFoo);

        Fqn fqn = Fqn.fromElements( subFoo.fooId );
        foo2SubFoosCache.put( fqn, subFoo,id, Boolean.TRUE );
    }

    public void remove ....

    public void update ....

    public Foo get(Long fooId)
    {
        return fooCache.get(fooId);
    }

    public SubFoo get(Long subFooId)
    {
        return subFooCache.get(subFooId);
    }


    public List<SubFoo> findSubFoo(Long fooId)
    {
        Fqn fqn = Fqn.fromElements( fooId );
        return foo2SubFoosCache.getKeys(fooId).stream().map( subFooId -> subFooCache.get(subFooId)).collect( Collector.list() );
    }
}
公共类服务
{
@注入
全基因组;
@注入
缓存fooCache;
@注入
缓存子焦点;
@注入
TreeCache Foo2 Subfooscache;
公共作废保存(Foo-Foo)
{
em.save(foo);
fooCache.put(foo.id,foo);
}
公共作废保存(子文件夹子文件夹)
{
em.save(subfo);
subfocache.put(subFoo.id,subfo);
Fqn Fqn=Fqn.fromElements(subfo.fooId);
foo2SubFoosCache.put(fqn,subFoo,id,Boolean.TRUE);
}
公共空间删除。。。。
公共无效更新。。。。
公共Foo-get(长fooId)
{
返回fooCache.get(fooId);
}
public子对象get(长子对象)
{
返回subfocache.get(子类);
}
公共列表findSubFoo(长fooId)
{
Fqn Fqn=Fqn.fromElements(fooId);
返回foo2SubFoosCache.getKeys(fooId.stream().map(subFooId->subFooCache.get(subFooId)).collect(Collector.list());
}
}

Infinispan具有索引功能。查找“Infinispan查询”

就我个人而言,我不太喜欢在缓存中建立索引。供应商之间的功能非常不同,即使存在。对于像你这样的问题,我认为没有理由做索引。我建议尝试使用任何缓存的最简单解决方案

解决方案1:

添加另一个缓存,即从foo id到子fo id的索引:
cache

由于此缓存仅存储ID,因此不会重复数据

解决方案2:

将子对象ID添加到父实体的缓存中:

class CachedFoo {
  Foo foo;
  List<Long> subFooIds;
}

Cache<Long, CachedFoo> fooCache;
类CachedFoo{
富富,;
列出子类;
}
缓存fooCache;
解决方案3:

如果您没有太多的数据和代码> Debug SufFoo很少使用,请考虑进程缓存中的一个带有签名“C”的替代方案。