Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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
JPA实现(或更广泛的Java ORM实现)是否支持可更新游标_Java_Hibernate_Orm_Eclipselink_Ibatis - Fatal编程技术网

JPA实现(或更广泛的Java ORM实现)是否支持可更新游标

JPA实现(或更广泛的Java ORM实现)是否支持可更新游标,java,hibernate,orm,eclipselink,ibatis,Java,Hibernate,Orm,Eclipselink,Ibatis,我希望Java可用的对象/关系映射(ORM)工具之一能够满足以下要求: 使用JPA或本机SQL查询获取大量行,并将它们作为实体对象返回 允许在对当前实体进行更改后,通过行(实体)进行迭代并持久化当前实体 我想逐行执行一个复杂的批处理操作(实际上,我正在将文件中已知的良好数据与数据库中的数据进行比较和协调)。如果更简单的话,我会使用JDBC并执行一些SQL;但是在这种情况下,我确实从直接从bean到数据库中得到了好处 在SQL中,我可以使用一个可更新的游标来高效地实现我的目标 作为参考,我正在

我希望Java可用的对象/关系映射(ORM)工具之一能够满足以下要求:

  • 使用JPA或本机SQL查询获取大量行,并将它们作为实体对象返回
  • 允许在对当前实体进行更改后,通过行(实体)进行迭代并持久化当前实体
我想逐行执行一个复杂的批处理操作(实际上,我正在将文件中已知的良好数据与数据库中的数据进行比较和协调)。如果更简单的话,我会使用JDBC并执行一些SQL;但是在这种情况下,我确实从直接从bean到数据库中得到了好处

在SQL中,我可以使用一个可更新的游标来高效地实现我的目标

作为参考,我正在嵌入式JavaH2环境中测试所有这些

JPA查询 我第一次天真的尝试是调用which,它返回实体bean,但它们是“断开连接的”。如果我调用
persistenceUnitUtil.getIdentifier(myEntity)
,它会抱怨它不是实体类型

冬眠 然后我研究了Hibernate,它支持。该接口允许我按名称获取单个列值,但不能按实体获取

日食 接下来是日食,它支持。我对这本书寄予厚望,并将其用于:

Query query = entityManager.createQuery(jpaQuery);
query.setHint("eclipselink.cursor", true);
CursoredStream cursoredStream = (CursoredStream)query.getSingleResult();
不幸的是
cursoredStream.next()再次返回实体的“断开连接”版本。所以,我找不到写回实体的方法

结论 我目前正在研究至少将实体的@Id作为查询的一部分传回的方法(不幸的是,我希望保持工具的灵活性,有时我将字符串作为键,有时是复合键对象)。这至少允许我遍历行,然后逐个查找和持久化每个实体

但是,我更喜欢的是有一个游标支持的迭代器,它将为我获取一个JPA连接的实体,并允许我对其进行更改和持久化

如果这不是其中一个ORM工具的已知特性,我可能不得不放弃并求助于好的旧JDBC。

伪代码(C#)

void执行(ISession会话,字符串文件路径)
{
int page=0;
int pagesize=5000;
int batchindex=int.MaxValue;
列表批次=新列表();
TextReader文件=新的StreamReader(文件路径)
弦线;
而((line=file.ReadLine)!=null)
{
如果(batchindex>batch.Count)
{
session.Flush();
session.Clear();
batch=session.CreateCriteria()
.AddOrder(Order.Asc())
.SetFirstResult(页面*页面大小)
.SetMaxResults(页面大小)
.List();
page++;
batchindex=0;
}
if(数据库的行数大于文件的行数
而(!LineIsForEntity(批处理[batchindex],行))
{
batchindex++;
//如果(batchindex>batch.Count)与上述相同
}
更新性(批次[batchindex],行);
}
session.Flush();
session.Clear();
}
根据数据类型和上下文,可能会有更好的代码

更新:使用C#进行随机访问,在使用(N)Hibernate时,这应该是有效的

const int pagesize=2000;
var nextbatch=可枚举。重复(0,页面大小)
.Select(=>file.ReadLine())
.TakeWhile(line=>line!=null);
字符串[]批;
while((batch=nextbatch.ToArray()).Length>0)
{
//忽略结果,我们只希望缓存中的实体
session.QueryOver()
.WhereRestrictionOn(e=>e.Id).In(batch.Select(line=>ExtractId(line)).ToList())
.List();
foreach(批处理中的字符串行)
{
更新(session.Get(ExtractId(行)),行);
}
session.Flush();
session.Clear();
}
正如评论中所说,使用entityManager替换会话,使用Java替换C#构造。如果实体是独立的,您甚至可以使用多线程、会话并行化while。

伪代码(C#)

void执行(ISession会话,字符串文件路径)
{
int page=0;
int pagesize=5000;
int batchindex=int.MaxValue;
列表批次=新列表();
TextReader文件=新的StreamReader(文件路径)
弦线;
而((line=file.ReadLine)!=null)
{
如果(batchindex>batch.Count)
{
session.Flush();
session.Clear();
batch=session.CreateCriteria()
.AddOrder(Order.Asc())
.SetFirstResult(页面*页面大小)
.SetMaxResults(页面大小)
.List();
page++;
batchindex=0;
}
if(数据库的行数大于文件的行数
而(!LineIsForEntity(批处理[batchindex],行))
{
batchindex++;
//如果(batchindex>batch.Count)与上述相同
}
更新性(批次[batchindex],行);
}
session.Flush();
session.Clear();
}
根据数据类型和上下文,可能会有更好的代码

更新:使用C#进行随机访问,在使用(N)Hibernate时,这应该是有效的

const int pagesize=2000;
var nextbatch=可枚举。重复(0,页面大小)
.Select(=>file.ReadLine())
.TakeWhile(line=>line!=null);
字符串[]批;
while((batch=nextbatch.ToArray()).Length>0)
{
//忽略结果,我们只希望缓存中的实体
session.QueryOver()
.WhereRestrictionOn(e=>e.Id).In(batch.Select(line=>ExtractId(line)).ToList())
.List();
foreach(批处理中的字符串行)
{
更新(session.Get(ExtractId(行)),行);
}
session.Flush();
session.Clear();
}
正如评论中所说,使用entityManager替换session,使用Java替换C#构造
void Execute(ISession session, string filepath)
{
    int page = 0;
    int pagesize = 5000;
    int batchindex = int.MaxValue;
    List<Entity> batch = new List<Entity>();

    TextReader file = new StreamReader(filepath)

    string line;
    while ((line = file.ReadLine) != null)
    {
        if (batchindex > batch.Count)
        {
            session.Flush();
            session.Clear();
            batch = session.CreateCriteria<Entity>()
                .AddOrder(Order.Asc(<same order as in file>))
                .SetFirstResult(page * pagesize)
                .SetMaxResults(pagesize)
                .List<Entity>();
            page++;
            batchindex = 0;
        }
        if (database has more rows than the file
        while (!LineIsForEntity(batch[batchindex], line))
        {
            batchindex++;
            // same if (batchindex > batch.Count) as above
        }

        UpdateEntity(batch[batchindex], line);
    }
    session.Flush();
    session.Clear();
}
const int pagesize = 2000;
var nextbatch = Enumerable.Repeat(0, pagesize)
    .Select(_ => file.ReadLine())
    .TakeWhile(line => line != null);

string[] batch;
while ((batch = nextbatch.ToArray()).Length > 0)
{
    // ignore results, we only want the entities in cache
    session.QueryOver<Entity>()
        .WhereRestrictionOn(e => e.Id).In(batch.Select(line => ExtractId(line)).ToList())
        .List();

    foreach(string line in batch)
    {
        Update(session.Get<Entity>(ExtractId(line)), line);
    }
    session.Flush();
    session.Clear();
}