Reputation: 3899
Since it isn't possible to use only Long Ids I am trying to use the generated String keys. I have three Classes User
, Topic
, Comments
with User
- 1:n - Topic
- 1:n -Comments
.
Class Comment:
@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;
Class User:
@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;
Class Topic:
@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;
Now when I am trying to save a new User, the following exception occurs
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.
Is it possible to let the String ID get generated without manually using the KeyFactory? If yes whats wrong with my code?
thanks
Upvotes: 0
Views: 1317
Reputation: 15577
IIRC IDENTITY strategy is to generate numeric (or Key) ids. If you were using JDO you could use UUID-style ids auto-generated. See https://developers.google.com/appengine/docs/java/datastore/jdo/creatinggettinganddeletingdata#Keys
Upvotes: 1
Reputation: 9935
I use TableGenerator
. It is useful whatever you want
id style. Let's say even if you would like to get Group
id like GRP0000001
and GRP0000500
etc..
You have to use property injection, not field injection in your entity. It is based on your setter ID method. If generated id is 201 by EntityManager
generate, entity manager will call setId()
in setter injection. If so, the id will be GRP0000201
.
My Example:
@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;
}
}
Upvotes: 0