GAE数据存储区使用JPA生成String键

时间:2012-10-25 09:55:00

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

由于不能仅使用Long Ids,我试图使用生成的String键。我有三个类UserTopicCommentsUser - 1:n - Topic - 1:n - Comments

课堂评论

@Entity
public class Comment implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
    private String key;
    @ManyToOne
    private User author;
    @ManyToOne
    private Topic topic;

班级用户:

@Entity
public class User implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
    private String key;

    @Unique
    private String username;

课程主题:

@Entity
public class Topic implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
    private String key;
    @ManyToOne(cascade = CascadeType.ALL)
    private User author;
    @OneToMany(cascade = CascadeType.ALL)
    private List<Comment> comments;

现在,当我尝试保存新用户时,会发生以下异常

Invalid primary key for User.  Cannot have a null primary key field if the field is unencoded and of type String.  Please provide a value or, if you want the datastore to generate an id on your behalf, change the type of the field to Long. 

是否可以在不手动使用KeyFactory的情况下生成String ID?如果是,我的代码有什么问题吗?

感谢

2 个答案:

答案 0 :(得分:1)

IIRC IDENTITY策略是生成数字(或键)ID。 如果您使用的是JDO,则可以使用自动生成的UUID样式ID。 见https://developers.google.com/appengine/docs/java/datastore/jdo/creatinggettinganddeletingdata#Keys

答案 1 :(得分:0)

我使用TableGenerator。无论您使用want id样式,它都很有用。即使您希望Group ID为GRP0000001GRP0000500等,我们也要说。 您必须在实体中使用属性注入,而不是字段注入。它基于您的setter ID方法。如果生成的id是EntityManager生成的201,则实体管理器将在setter注入中调用setId()。如果是,则ID为GRP0000201

我的例子:

@Entity
@TableGenerator(name = "GROUP_GEN", table = "ID_GEN", pkColumnName = "GEN_NAME", 
                valueColumnName = "GEN_VAL", pkColumnValue = "GROUP_GEN", allocationSize = 1)
@Access(value = AccessType.FIELD)
public class Group implements Serializable {
    @Transient
    private String id;
    private String name;
    //name getter and setter
    public void setId(String id) {
        if(id != null) {
            this.id = Utils.formatId(id, "GRP", 10);    
        }
    }

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "GROUP_GEN")
    @Access(value = AccessType.PROPERTY)
    public String getId() {
        return id;
    }
}

Utils.java

public class Utils {
    /**
     * E.g.
     * Input: id=523, prefix="AAA", maxLength=15
     * Output: AAA000000000523
     */
    public static String formatId(String id, String prefix, int maxLength) {
        if (!id.startsWith(prefix)) {
            int length = id.length() + prefix.length();
            for (; (maxLength - length) > 0; length++) {
                id = '0' + id;
            }
            id = prefix + id;
        }
        return id;
    }
}
相关问题