ebean
ebean copied to clipboard
NullPointerException thrown when updating an entity with multiple primary keys
This exception occurs in both 12.16.1 and the latest 13.25.1 versions, I have not tried earlier versions.
Expected behavior
Expect the value of the col column to be updated to "success"
Actual behavior
java.lang.NullPointerException: Cannot invoke "io.ebean.bean.EntityBean._ebean_getField(int)" because "bean" is null
Steps to reproduce
Define the table under postgresql and add test records (the same problem occurs when testing under mysql)
DROP TABLE IF EXISTS "public"."test_multi_pk_update";
CREATE TABLE "public"."test_multi_pk_update" (
"p1" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
"p2" varchar(32) COLLATE "pg_catalog"."default" NOT NULL,
"col" varchar(64) COLLATE "pg_catalog"."default"
);
INSERT INTO "public"."test_multi_pk_update" VALUES ('p1', 'p2', 'column_content');
ALTER TABLE "public"."test_multi_pk_update" ADD CONSTRAINT "test_id_class_pkey" PRIMARY KEY ("p1", "p2");
Define java beans
@Embeddable
public class TestMultiPkUpdateId {
@AttributeOverride(name = "p1", column = @Column(name = "p1"))
@Column(name = "p1")
private String p1;
@AttributeOverride(name = "p2", column = @Column(name = "p2"))
@Column(name = "p2")
private String p2;
public String getP1() {
return this.p1;
}
public void setP1(String p1) {
this.p1 = p1;
}
public String getP2() {
return this.p2;
}
public void setP2(String p2) {
this.p2 = p2;
}
@Override
public int hashCode() {
int result = 17 * 31;
result = 31 * result + Objects.hashCode(p1);
result = 31 * result + Objects.hashCode(p2);
return result;
}
@Override
public boolean equals(Object that) {
if (this == that) {
return true;
}
if (!(that instanceof TestMultiPkUpdateId other)) {
return false;
}
if (!Objects.equals(p1, other.p1)) return false;
return Objects.equals(p2, other.p2);
}
}
@Entity(name = "TestMultiPkUpdate")
@Table(name = "test_multi_pk_update")
@IdClass(TestMultiPkUpdateId.class)
public class TestMultiPkUpdate {
@Id
@Column(name = "p1")
private String p1;
@Id
@Column(name = "p2")
private String p2;
@Column(name = "col", length = 64, nullable = true)
private String col;
public String getP1() {
return this.p1;
}
public void setP1(String p1) {
this.p1 = p1;
}
public String getP2() {
return this.p2;
}
public void setP2(String p2) {
this.p2 = p2;
}
public String getCol() {
return this.col;
}
public void setCol(String col) {
this.col = col;
}
}
Execute the following code to reproduce the exception:
TestMultiPkUpdate testMultiPk = new TestMultiPkUpdate();
testMultiPk.setP1("p1");
testMultiPk.setP2("p2");
testMultiPk.setCol("success");
// Expect the value of the col column to be updated to "success". And the actual exception is thrown:
// java.lang.NullPointerException: Cannot invoke "io.ebean.bean.EntityBean._ebean_getField(int)" because "bean" is null
DB.update(testMultiPk);
Caused by: java.lang.NullPointerException: Cannot invoke "io.ebean.bean.EntityBean._ebean_getField(int)" because "bean" is null
at io.ebeaninternal.server.properties.EnhanceBeanPropertyAccess$Getter.get(EnhanceBeanPropertyAccess.java:57)
at io.ebeaninternal.server.deploy.BeanProperty.getValue(BeanProperty.java:768)
Hi. I just want to say that this is an easily reproducible exception, and it is very common to use multiple columns as primary keys, I look forward to this exception being resolved. Or am I using it incorrectly? Please guide me past this blocker, thank you very much
Can you change your code to use embeddedId as composite PK? See https://github.com/ebean-orm/ebean/blob/master/ebean-test/src/test/java/org/tests/model/composite/ROrder.java for an example
Can you change your code to use embeddedId as composite PK? See https://github.com/ebean-orm/ebean/blob/master/ebean-test/src/test/java/org/tests/model/composite/ROrder.java for an example
Thanks for the guidance, I did successfully get the record updated using @EmbeddedId. I want to confirm that using @IdClass is not supported? Or is this a problem? Because I do tend to use @IdClass to map concatenated primary keys.
I noticed that ebean docs mentioned using @IdClass to map concatenated primary keys: https://ebean.io/docs/interesting/embedded-id
Well I saw this location where there are unit tests using @IdClass: https://github.com/ebean-orm/ebean/blob/master/tests/test-java16/src/test/java/org/example/records/RecordIdClassTest.java