英文:
Update entity data using Quarkus and PanacheRepository is not working
问题
我正在使用 Quarkus 和 PanacheRepository 进行一些测试,但在更新实体数据时遇到了问题。更新操作无法正常工作,字段的值没有被更新。
简而言之:我创建了一个实体并将数据持久化,然后在另一个请求中,我通过 repository.findById(id)
从数据库获取实体,更改了一些字段的值,但是新值没有持久化到数据库中。我尝试在此之后调用 repository.persist(person)
,但行为仍然相同,数据没有更新。
我尝试了 Quarkus 版本 1.9.0.Final、1.9.0.CR1、1.8.3.Final。
我正在使用 PostgreSQL 12。我还尝试了 MySQL 5.7.26。
我使用 Eclipse 2020-06(4.16.0)仅用于编写代码,并在命令行中运行应用程序,使用命令:./mvnw compile quarkus:dev
。
我创建了一个全新的简单应用程序,但行为仍然相同。以下是主要配置和一些代码片段:
pom.xml
<!-- 省略部分 -->
application.properties:
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = 用户名
quarkus.datasource.password = 密码
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/testpanache
# 在启动时删除并重新创建数据库(使用 `update` 仅更新模式)
quarkus.hibernate-orm.database.generation = drop-and-create
实体:
@Entity
public class Person {
@Id @GeneratedValue public Long id;
public String name;
@Override
public String toString() {
return "Person [id=" + id + ", name='" + name + "']";
}
}
REST 资源:
@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"; // 无效
// repository.persist(person); // 无效
// repository.persistAndFlush(person); // 无效
repository.getEntityManager().merge(person); // 无效
return person;
}
}
Repository:
@ApplicationScoped
public class PersonRepository implements PanacheRepository<Person> {
}
我使用 curl 发出了一些请求来演示此行为:
$ 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"}]
所以,列表开始为空,第二个 POST 请求创建了一个带有 "some name" 的 Person,如第三个请求所示;第四个请求执行了一个 PUT 操作,旨在将名称更改为 "updated updated updated",但第五个请求显示名称未更新。
虽然这并不是必要的,但我尝试将实体扩展为 PanacheEntity
,并使用 Person.findById(id)
来查找实体,这样后续的更新操作确实生效了。但这不是我的重点,我想使用 PanacheRepository,并且想要了解我漏掉了什么。
英文:
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
得分: 7
请考虑使用getter/setter访问您的实体,以便Hibernate代理能够正常工作。
@Entity
public class Person {
@Id @GeneratedValue public Long id;
private String name; // <--- 私有字段
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", name= '" + name + "']";
}
}
并且在您的资源类中:
@PUT
@Path("{id}")
@Transactional
public Person update(@PathParam("id") Long id) {
Person person = repository.findById(id);
person.setName("updated updated updated"); // <--- 这种方式有效
repository.persist(person);
return person;
}
英文:
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;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论