【问题标题】:Relationships in Google App EngineGoogle App Engine 中的关系
【发布时间】:2011-08-30 10:44:00
【问题描述】:

我只有一周的 GAE/Java 经验,并尝试将遗留应用程序(使用 PHP/MySQL 开发)移植到 GAE+JDO。我现在在创建两个表(GAE 中的种类)之间的关系时遇到了一个基本问题。

就是这样: 我们有一个保存用户身份验证信息的 Users 表。它还有一个字段user_role,其中存储了role_id,它实际上是另一个表user_roles的外键。

从 GAE 中的 Entity-Relationship 文档中,我了解到 DataStore 不支持外键关系,并通过改编文档中的 Employee-ContactInfo 示例设计了 Users 类。

当我执行应用程序时,每次我在 Users 表中添加条目时都会插入 user_roles 类型。 user_roles 种类应该只有三个静态值。但是,当我在 Users 中输入更多记录时,这具有冗余值。

我认为我遗漏了一些非常琐碎的事情,但由于我对数据存储缺乏经验,我无法弄清楚。如果有人能指导我解决这个问题,那就太好了。

代码如下:

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Users {

        @PrimaryKey
        @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
        private Key key;

        @Persistent
        private String userName;

        @Persistent
        private String password;

        @Persistent
        private String salt;

        @Persistent
        private Date createdDate;

        @Persistent
        private Key createdBy;

        @Persistent
        private Date lastLogin;

        @Persistent
        private boolean status;

        @Persistent
        private String authKey;

        @Persistent(defaultFetchGroup="true")
        private SecurityRole securityRole;

        @Autowired
        SecurityRepository securityRepository ;

        public SecurityPrincipals(String userName, String password,SecurityRole securityRole,boolean status) {
                this.securityRole = securityRole;
                this.userName = userName;
                this.password = password;
                this.status = status;
        }

   //getters and setters
}

角色定义:

@PersistenceCapable(detachable="true")
public class SecurityRole {

        @PrimaryKey
        @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
        private Key key;

        @Persistent
        private String securityRoleName;

        @Persistent
        private String securityRoleDescription;

        @Persistent
        private String securityRoleStatus;

        @Persistent
        private Date securityRoleCreatedDate;

        public SecurityRole(String securityRoleName, String securityRoleDescription, String securityRoleStatus,String securityBaseType)
        {
                this.securityRoleName = securityRoleName;
                this.securityRoleDescription = securityRoleDescription;
                this.securityRoleStatus = securityRoleStatus;
                this.securityBaseType = securityBaseType;
        }
// getters and setters
}

Controller的相关代码:

SecurityRole securityRole = securityRepository.getSecurityRole( securityRoleName);
users = new Users(userName,password,status,securityRole);
iUserRepository.save(employeeDetails);

这里是getSecurityRole的定义:

public SecurityRole getSecurityRole(String securityRoleName)
        {
                      PersistenceManagerFactory pmf = this.jdoTemplate.getPersistenceManagerFactory();
                PersistenceManager pm = pmf.getPersistenceManager();
                try {
                        Query query = pm.newQuery( SecurityRole.class);
                        query.declareImports("import java.lang.String");
                        query.declareParameters("String securityRoleName");
                        query.setFilter("this.securityRoleName == securityRoleName");
                        List<SecurityRole> securityRoles = (List<SecurityRole>)query.execute(new String(securityRoleName));
                        SecurityRole temp = null;
                        for(SecurityRole securityRole: securityRoles)
                        {
                                temp = securityRole;
                        }
            return temp;
                }
                finally {
                        pm.close();
                }
        }

这里是iUserRepository.save()的定义:

public void save(Users user) {
               jdoTemplate.makePersistent(companyDetails);
}

【问题讨论】:

  • 除了您必须对代码进行的所有修改使其不可编译之外,我看不出有任何问题。也许 securityRepository.getSecurityRole 返回实际角色的副本?
  • 是的,securityRepository.getSecurityRole 返回实际角色的副本。我已经添加了代码 sn-p。
  • 您的代码 sn-p 没有显示任何正在制作的副本。它返回从查询返回的最后一个角色。
  • 正如我所说,我看不出代码有什么问题。我认为问题可能是存储库返回了副本而不是实际角色,但事实并非如此,所以它一定是我缺少的其他东西。

标签: java google-app-engine google-cloud-datastore


【解决方案1】:

在 Users 类中,您已经定义了属性

@Persistent(defaultFetchGroup="true")
private SecurityRole securityRole;

此语句在 GAE 数据存储中创建“拥有”关系,这意味着当您创建 Users 类的对象时,还将创建 SecurityRole 类的对象。

您需要的是一个无主关系,可以按如下方式创建:

@Persistent(defaultFetchGroup="true")
private Key securityRole;

这样,每次创建 Users 类的实例时都不会创建 SecurityRole 对象。有关拥有和非拥有关系的更多信息,请查看http://code.google.com/appengine/docs/java/datastore/jdo/relationships.html

希望这会有所帮助!

【讨论】:

  • 感谢您的解释,这真的很有帮助。事实上,我已经发布了另一个问题来澄清这个疑问。我知道如何在拥有关系中检索“引用对象”,但我仍然不确定在无拥有关系的情况下如何编写查询。能否请您对此提供一些见解?
  • 您可以通过执行两个查询来做到这一点。第一个获取用户实体,另一个获取 SecurityRole 实体。然后以编程方式组合结果。另外,您能否接受答案以提高我们的声誉等级?
  • 谢谢,我最初是作为一种解决方法这样做的,但与 JOIN 相比,它看起来是一个糟糕的解决方案(你知道我来自 RDBMS 背景)。但是,我需要接受这个事实。
  • 我完全理解,我也来自相同的背景 :) 希望我们能够在继续使用 App Engine 时提供更有效的解决方案。很高兴我帮助了:)
猜你喜欢
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-20
  • 2011-07-05
相关资源
最近更新 更多