How to set id in model? I try this code:
public Community(Long id, ...) {
this.id = id;
....
}
But when I do this:
Communtiy c = new (1, ...);
c.save();
Hibernate say:
Execution exception PersistenceException occured : org.hibernate.PersistentObjectException: detached entity passed to persist: models.Community
You can do this by extending from play.db.jpa.GenericModel instead of play.db.jpa.Model. This will allow you to set the primary key manually.
In fact, what Model does is extend from GenericModel and because it is very common to do so Model automatically generates primary keys ( by using #Id #GeneratedValue public Long id ). But if for whatever reason you want to set a custom primary key, then extending from GenericModel is the way to go.
Official documentation here.
Example
#Entity
public class Community extends GenericModel {
#Id
public Long id;
public Community (Long id) {
this.id = id;
}
}
Try not set id on your own, id should be loaded to model after save.
Related
What I want to achieve to take auto generated ID, hash it and save it into other field in the class, but at the stage of creating object by constructor ID is not yet generated. Any workaround ideas?
#Entity
public class MyClass {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.AUTO)
Long id;
String hashID;
MyClass(){
this.hashID = Utils.hashID(id);
}
//setters and getters
}
```
One way that I can think of is you can use an entity lifecycle callback event like #PostLoad which is called when the entity is loaded in the persistence context, and initialize your hashed field from the id.
E.g.
#Entity
public class MyClass {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Long id;
String hashID;
#PostLoad
public void postLoad() {
// Here id is initialized
this.hashID = Utils.hashID(id);
}
}
I have to manage a Datatransfer between 2 DBs (mssql) with hibernate.
When i load an object from one DB with session.get() it already has a private key. Then i need to persist it to the other DB with anotherSession.replicate(Object o).
My Problem ist, that the given PK is not persisted but replaced by another one.
PS: Both the srcTable and the destTable have PK generation Identity and it needs to stay that way.
If you map an Entity ID with generation "identity", Hibernate will always generate a new ID as soon as you try to persist it. You will have to switch the generation to "assigned" to keep your old ID.
If you have something like it
#Entity
public class Project {
#Id #GeneratedValue long id; // still set automatically
}
You have to remove the #GeneratedValue annotation from id field. Else jpa will generate a value for id before insertion.
#Entity
public class Project {
#Id long id; // must be initialized by the application
:
}
Solution To Your Problem
Create a an entity containing all the mapping definition.
Create a ID field in your new class without the #Generated value annotation.
Clone the old entity to this new one.
Persist this new entity.
Now if you create a subclass extending your entity then the whole
process becomes very easy.
Sample Code For This Solution
Existing Entity
#Entity
#Table(name="EJB_PROJECT")
public class OldEntity implements Serializable {
#Id
#Column(name="PROJECT_ID", primaryKey=true)
#GeneratedValue
Integer id;
}
New Entity
#Entity
#Inheritance(strategy=SINGLE_TABLE)
#Table(name="EJB_PROJECT")
public class NewEntity extends OldEntity {
#Id
#Column(name="PROJECT_ID", primaryKey=true)
Integer id;
// Constructor to clone old entity's id
public NewEnity(OldEntity old) {
this.id = old.id;
}
}
Persisting code
em.persist(new NewEntity(oldEntity));
I'm getting the following error:
Could not determine type for: java.util.Set, at table: Ruleset, for columns: [org.hibernate.mapping.Column(ruleset)]
class snippet:
#Entity
public class Ruleset implements java.io.Serializable {
#Id
#OneToOne(targetEntity = RulesetStatus.class)
private Integer id;
private Set<Rule> ruleset = new HashSet<Rule>(0);
public Ruleset() {
}
public Ruleset(Integer ID, Set<Rule> ruleset) {
this.id = ID;
this.ruleset = ruleset;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Set<Rule> getRuleSet(){
return this.ruleset;
}
public void setRuleset(Set<Rule> ruleset) {
this.ruleset = ruleset;
}
}
I've figured out that annotating ruleset as Transient makes the problem go away, but then ruleset won't be persisted to the DB. How do I tell hibernate about the type of this field?
I'm very new to Hibernate so I'm totally lost here.
__________________________Edit__________________________
The actual relationship should have been #ManyToMany as a rule can be in many rulesets and a ruleset can have many rules.
I added the #ManyToMany annotation to the set, then did not have a corresponding set in the Rule Class to map to. I added the set in the rule class, added the #ManyToMany annotation to that, and no I have no errors.
Does this seem correct?
By default, all fields (or properties) are mapped in JPA. That's why you have to tell the JPA provider what your Set is supposed to map (one-to-many, many-to-many, #ElementCollection, etc.), or map it as #Transient to tell the provider that you don't want the property to be persisted.
Good day Guys,
I want to create Models that don't use the default #Id auto generation for Playframework and Ebeans. I have seen online that there are options for Using GenericModel, however that class doesn't seem to be included in version 2.3x. I have done this in order to workaround it but i still fall short my aim
public class ProductVariants extends Model
{
#Id
String id;
public String getId() {
return (this.id == null) ? UUID.randomUUID().toString() : this.id;
}
public void setId(String id) {
this.id = id;
}
}
The issue with this is that i have to manually set the ID before i can save the object e.g.
productVariant.setId(productVariant.getId());
productVariant.save();
Both for a primary model and all it related models with a OneToMany relationship, and it is currently giving me issues when i bind from the view to the Model object with error ERROR executing DML bindLog[] error[Field 'id' doesn't have a default value]]].
Please any help will be appreciated.
Good day Guys,
I finally fixed this by using the UUID class that ships with the JDK. So when you are creating your Models you create them with the
#Id
public java.util.UUID id
Also in the routes file if you need to map to a record by the ID you can do that by doing something like this
GET /:pid/edit controllers.Application.edit(pid: java.util.UUID)
I have entity zika1
public class zika1 {
#Id
int id;
String sika;
#OneToMany(cascade=CascadeType.ALL,orphanRemoval=true)
#JoinColumn
List<zika2> zikas=new ArrayList<zika2>();}
and entity zika2
#Table(name = "zika2", uniqueConstraints = #UniqueConstraint(columnNames = { "b" }))
public class zika2 {
#Id
String a;
#Column(unique=true)
String b;}
and this method:
public void testuniqu()
{
zika1 zik=super.find(1);
zika2 zik22=new zika2();
zik22.setA("karkar");
zik22.setB(zik.getZikas().get(0).getB());
zik.getZikas().remove(0);
zik.getZikas().add(zik22);
super.save(zik);
}
this throw a unique constraint exception but actually i am deleting the first entity . so jpa(eclipse link) not running this operation in the same db transaction.
is there a way to tell jpa to run the delete before the insert operation for the new zika2 entity?
I think that is a normal flow, because EclipseLink doesn't execute commands in order you write it. So you need to tell EclipseLink some hint, that "delete" operation should be the first one. According to :
http://wiki.eclipse.org/Using_Advanced_Unit_of_Work_API_%28ELUG%29#How_to_Use_the_setShouldPerformDeletesFirst_Method_of_the_Unit_of_Work, you should use setShouldPerformDeleteFirst.