Java 在GAE上检索/记录多个实体的最便宜方法
我有一个具体的案例让我产生了一些疑问: 我的班级A与B有一对多的关系:Java 在GAE上检索/记录多个实体的最便宜方法,java,google-app-engine,jpa,transactions,google-cloud-datastore,Java,Google App Engine,Jpa,Transactions,Google Cloud Datastore,我有一个具体的案例让我产生了一些疑问: 我的班级A与B有一对多的关系: A 1----->* B 据我所知,这使得它们的相关实例属于同一个实体组。 我必须检索一个特定的A实例和它的一个B实例,所以我搜索A并遍历它的B列表以找到特定的B(总是按Id搜索)。之后,我更改A和B的一个属性,并通过合并A提交我的更改。下面是我的问题: 知道我必须检索A和B(因为我必须修改这两个),我应该进行2次搜索而不是迭代B列表吗 进行2次搜索,如果我只保留A,对B的修改将被保留 在这种情况下,问题1和2的
A 1----->* B
据我所知,这使得它们的相关实例属于同一个实体组。
我必须检索一个特定的A实例和它的一个B实例,所以我搜索A并遍历它的B列表以找到特定的B(总是按Id搜索)。之后,我更改A和B的一个属性,并通过合并A提交我的更改。下面是我的问题:
@Entity
public class A
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private int aField;
@OneToMany(cascade={CascadeType.ALL})
private List<B> bList;
//...
}
@Entity
public class B
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private int someBField;
// no way to get A from here...
//...
}
public void someService1(Key aKey, Key bKey)
{
//...
// Here, I'm sure that bKey is of an entity son of aKey entity (I trust the client)
A a = entityManager.find(A.class, aKey);
a.setAField(a.getAField()++);
for(B b : a.getBList())
if(b.getKey().equals(bKey))
b.setSomeBField(b.getSomeBField()++);
entityManager.merge(a);
//...
}
public void someService2(Key aKey, Key bKey)
{
//...
// Here, I'm sure that bKey is of an entity son of aKey entity (I trust the client)
A a = entityManager.find(A.class, aKey);
a.setAField(a.getAField()++);
B b = entityManager.find(B.class, bKey);
b.setSomeBField(b.getSomeBField()++);
entityManager.merge(a);
//...
}
@实体
公共A类
{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私钥;
私人外场;
@OneToMany(cascade={CascadeType.ALL})
私人名单;
//...
}
@实体
公共B级
{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私钥;
萨姆博菲尔德私人酒店;
//没有办法从这里得到一个。。。
//...
}
公共服务1(密钥aKey,密钥bKey)
{
//...
//在这里,我确信bKey是aKey实体的子实体(我信任客户)
A=entityManager.find(A.class,aKey);
a、 setAField(a.getAField()++);
对于(B:a.getBList())
如果(b.getKey().equals(bKey))
b、 setSomeBField(b.getSomeBField()++);
entityManager.merge(a);
//...
}
公共服务2(密钥aKey,密钥bKey)
{
//...
//在这里,我确信bKey是aKey实体的子实体(我信任客户)
A=entityManager.find(A.class,aKey);
a、 setAField(a.getAField()++);
B=实体管理器查找(B.class,bKey);
b、 setSomeBField(b.getSomeBField()++);
entityManager.merge(a);
//...
}
好吧,如果我做的每件事都是对的,那么someService1和someService2都会做同样的事情。哪一个更好?如果我理解正确,您不必重复任何内容,而是在您喜欢的任何
查询中使用。示例(Python):
如果您正在使用Java,您将在查询中使用()。如果您知道id(并且您说您正在按id搜索),那么只需对A执行em.find
,对B执行em.find
。两次调用。遗憾的是,JPAAPI没有em.findAll
。另一方面,JDO确实有pm.getObjectsById
对不起,我忘了说我使用Java和JPA。我不明白,过滤器的使用如何转化为搜索或数据存储读取的数量?我如何使用它检索实体和祖先?请注意,我正在使用ID查找这两个实例。@Roberto我现在必须走了。。但一般来说,如果在数据存储中使用关系,则必须熟悉可应用于查询的过滤器。。我建议您浏览一下概述(最后一个链接)并熟悉它。如果有一些示例代码开始,它将非常有用。这个问题太抽象了,很难回答。例如,您说一对多关系意味着它们都在同一个实体组中,但这不是建模此类关系的唯一方法。如果是这样建模的,您可以使用祖先查询在Bs上迭代——为什么要使用Bs的ID?等等。如果您展示了您实际拥有的代码并提出了一些有针对性的问题,那么所有这些猜测都是不必要的。@GuidovanRossum好的,我编辑了我的问题。我需要一个特定的B,所以我迭代并使用id来查找它。问题其实很简单(但很难表达):迭代一个列表,我已经找到了一个元素,但是,忘记这个列表,直接搜索这个元素,因为我有id,这两者之间有什么区别(在成本方面)。谢谢。你这么说是因为它比迭代B列表便宜,对吧?想想数据存储访问。。。获取A,然后获取B实体的列表。。。或者得到A,得到B。可能两个数据存储都访问(看看日志,它告诉你(谷歌插件的最新版本)),但后者检索的信息(带宽)更少。我认为在迭代列表时(列表中的每个元素搜索一次)会花费更多的读取操作。这取决于GAE如何管理它。。。这是一个电话。。。而是对许多实体对象的调用。我的建议是,只需要一个实体,所以永远不会花费更多
@Entity
public class A
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private int aField;
@OneToMany(cascade={CascadeType.ALL})
private List<B> bList;
//...
}
@Entity
public class B
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Key key;
private int someBField;
// no way to get A from here...
//...
}
public void someService1(Key aKey, Key bKey)
{
//...
// Here, I'm sure that bKey is of an entity son of aKey entity (I trust the client)
A a = entityManager.find(A.class, aKey);
a.setAField(a.getAField()++);
for(B b : a.getBList())
if(b.getKey().equals(bKey))
b.setSomeBField(b.getSomeBField()++);
entityManager.merge(a);
//...
}
public void someService2(Key aKey, Key bKey)
{
//...
// Here, I'm sure that bKey is of an entity son of aKey entity (I trust the client)
A a = entityManager.find(A.class, aKey);
a.setAField(a.getAField()++);
B b = entityManager.find(B.class, bKey);
b.setSomeBField(b.getSomeBField()++);
entityManager.merge(a);
//...
}
query.filter('height >', 42).filter('city = ', 'Seattle')
query.filter('user = ', users.get_current_user())