Update entity data using Quarkus and PanacheRepository is not working

28.2k views Asked by At

I'm doing some tests with Quarkus and PanacheRepository and I'm getting trouble in update an entity data. The update doesn't work, the field values are not updated.

In short: I create an entity and persist the data, after that in another request I get the entity from database using repository.findById(id);, change some field value, but the new value is not persisted in the database. I tried call repository.persist(person); after but the behavior is the same, the data is not updated.

I tried this with Quarkus version 1.9.0.Final, 1.9.0.CR1, 1.8.3.Final

I'm using postgreSQL 12. I also tried with mysql 5.7.26

I use Eclipse 2020-06 (4.16.0) only to write code and I run the application in the command line, with: ./mvnw compile quarkus:dev

I've created a brand new simple application and the behavior is the same. Here is the main configurations and some code snippets:

pom.xml

    <properties>
        <compiler-plugin.version>3.8.1</compiler-plugin.version>
        <maven.compiler.parameters>true</maven.compiler.parameters>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <quarkus-plugin.version>1.9.0.Final</quarkus-plugin.version>
        <quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
        <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
        <quarkus.platform.version>1.9.0.Final</quarkus.platform.version>
        <surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-jsonb</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-hibernate-orm-panache</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-jdbc-postgresql</artifactId>
        </dependency>
    </dependencies>

application.properties:

quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = theusername
quarkus.datasource.password = thepassword
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/testpanache

# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.database.generation = drop-and-create

Entity:

@Entity
public class Person {

    @Id @GeneratedValue public Long id;
    
    public String name;

    @Override
    public String toString() {
        return "Person [id=" + id + ", name= '" + name + "']";
    }   
}

REST Resource:

@Path("/people")
@Produces(MediaType.APPLICATION_JSON)
public class PersonResource {

    @Inject
    PersonRepository repository;
    
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public List<Person> hello() {
        return repository.listAll();
    }
    
    @POST
    @Transactional
    public void create() {
        Person person = new Person();
        person.name = "some name";
        repository.persist(person);
    }

    @PUT
    @Path("{id}")
    @Transactional
    public Person update(@PathParam("id") Long id) {
        Person person = repository.findById(id);
        person.name = "updated updated updated"; // does not work
//      repository.persist(person); // does not work
//      repository.persistAndFlush(person); // does not work
        repository.getEntityManager().merge(person); // does not work
        return person;
    }
}

Repository:

@ApplicationScoped
public class PersonRepository implements PanacheRepository<Person> {
}

I made some requests using curl to demonstrate the behavior:

$ curl -w "\n" http://localhost:8080/people
[]

$ curl -X POST http://localhost:8080/people

$ curl -w "\n" http://localhost:8080/people
[{"id":1,"name":"some name"}]

$ curl -X PUT http://localhost:8080/people/1
{"id":1,"name":"updated updated updated"}

$ curl -w "\n" http://localhost:8080/people
[{"id":1,"name":"some name"}]

So, the list starts empty, the second POST request creates a Person with "some name", as shown by the third request; the fourth request does a PUT that is intended to change the name to "updated updated updated", but the fifth request shows the name was not updated.

Although it's not needed, I tried repository.persist(person);, repository.persistAndFlush(person);, and even repository.getEntityManager().merge(person); (one each time) as show in the PersonResource snippet above. But none of them made effect.

What I am missing?

PS.: I tried to change my entity to extends PanacheEntity and used Person.findById(id); to find the entity, this way the subsequent updates did make effect. But it's not my point, I wanna use PanacheRepository and want to understand what I'm missing with this.

1

There are 1 answers

3
Tiago Aquino On BEST ANSWER

Please consider accessing your entity using getter/setter, so Hibernate Proxies will work properly.

@Entity
public class Person {

    @Id @GeneratedValue public Long id;
    
    private String name;  // <--- private field

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", name= '" + name + "']";
    }   
}

and in your resource:


    @PUT
    @Path("{id}")
    @Transactional
    public Person update(@PathParam("id") Long id) {
        Person person = repository.findById(id);
        person.setName("updated updated updated");  // <--- this way works
        repository.persist(person);
        return person;
    }