Hibernate Rest状态码:200但实体未保存。

5

我正在尝试使用Hibernate和Jersey保存一个实体。

我尝试发送的JSON是:

{
"firstname":"Jon",
"middlename":"J",
"lastname":"Smith",
"dob":"10-10-1990",
"gender":"male"
}

当我使用Postman发送请求时,返回Status: 200 OK,但记录未保存到数据库中。
我使用的数据库是Neo4j。
这是我的PersonDAO类:
package com.Neo4jRestAPI;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import org.hibernate.HibernateException;

import com.google.gson.Gson;

public class PersonDAO {

    public void addPerson(Person person){

        try {
            EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistence");
            EntityManager em = emf.createEntityManager();
            EntityTransaction tx = em.getTransaction();
            tx.begin();

            Person p = new Person();

            p.setFirstname(person.getFirstname());
            p.setMiddlename(person.getMiddlename());
            p.setLastname(person.getLastname());
            p.setDob(person.getDob());
            p.setGender(person.getGender());

            em.persist(p);
            em.flush();     
            tx.commit();
            em.clear(); 
            em.close(); 
            emf.close();
            }
        catch ( Exception e ) {
            e.printStackTrace();
        }
    }
}

这是我尝试发送数据的方法:
@POST
@Path("/person")
@Consumes("application/json")
public Response addPerson(Person person){

     person.setFirstname(person.getFirstname());
     person.setMiddlename(person.getMiddlename());
     person.setLastname(person.getLastname());
     person.setDob(person.getDob());
     person.setGender(person.getGender());

     PersonDAO dao = new PersonDAO();

     dao.addPerson(person);

     return Response.ok().build();
}

有没有人知道我在这里做错了什么?

编辑

我可以使用 native query 保存实体,但这种方式不会自动生成id。 我仍然无法按照上述方法保存实体

当我删除@GeneratedValue并在JSON中指定id 时,我就能够保存实体,因此我认为问题出在那里。 我尝试过几种策略,但都没有起作用。

这是我尝试自动生成id 的方式:

@Entity
@Table(name="Person")
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

此外,当我打印方法getId()时,会得到自增的值。
以下是已执行的Cypher查询:
"{"statements":[{"statement":"CREATE (n:ENTITY:Person {props}) RETURN n","parameters":{"props":{"firstname":"Jon","gender":"male","dob":"10-10-1990","middlename":"J","id":99,"lastname":"Smith"}},"includeStats":false,"resultDataContents":["graph"]}]}"

我也遇到了事务回滚错误,但是它没有说明为什么被回滚:

"Neo.ClientError.Transaction.TransactionNotFound","message":"Unrecognized transaction id. Transaction may have timed out and been rolled back

这是我的persistence.xml文件。
<?xml version="1.0"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
         version="2.0">

<persistence-unit name="persistence">
    <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
    <properties>
        <property name="hibernate.ogm.datastore.provider" value="neo4j_http"/>
        <property name="hibernate.ogm.neo4j.database_path" value="C://path//to//database"/>
        <property name="hibernate.ogm.datastore.host" value="localhost:7474"/>
        <property name="hibernate.ogm.datastore.username" value="neo4j"/>
        <property name="hibernate.ogm.datastore.password" value="root"/>
    </properties>
  </persistence-unit>
  </persistence>

编辑

这是我得到的堆栈跟踪:

log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. 

当我使用log4j并添加BasicConfigurator.configure()时,我会得到以下错误信息(由于日志太长,无法在此贴出完整内容,所以我只贴出了抛出错误的部分):

2342 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "{"statements":[{"statement":"CREATE (n:ENTITY:Person {props}) RETURN n","parameters":{"props":{"firstname":"Anna","gender":"female","dob":"10-10-1990","middlename":"J","id":57,"lastname":"Smith"}},"includeStats":false,"resultDataContents":["graph"]}]}"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "HTTP/1.1 200 OK[\r][\n]"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Date: Tue, 03 Oct 2017 09:01:10 GMT[\r][\n]"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Content-Type: application/json[\r][\n]"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Access-Control-Allow-Origin: *[\r][\n]"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Content-Length: 372[\r][\n]"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Server: Jetty(9.2.z-SNAPSHOT)[\r][\n]"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "[\r][\n]"
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.DefaultClientConnection  - Receiving response: HTTP/1.1 200 OK
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << HTTP/1.1 200 OK
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Date: Tue, 03 Oct 2017 09:01:10 GMT
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Content-Type: application/json
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Access-Control-Allow-Origin: *
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Content-Length: 372
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Server: Jetty(9.2.z-SNAPSHOT)
2345 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.client.DefaultHttpClient  - Connection can be kept alive indefinitely
2346 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "{"commit":"http://localhost:7474/db/data/transaction/53/commit","results":[{"columns":["n"],"data":[{"graph":{"nodes":[{"id":"10","labels":["ENTITY","Person"],"properties":{"firstname":"Anna","gender":"female","dob":"10-10-1990","middlename":"J","id":57,"lastname":"Smith"}}],"relationships":[]}}]}],"transaction":{"expires":"Tue, 03 Oct 2017 09:02:10 +0000"},"errors":[]}"
2346 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection [id: 1][route: {}->http://localhost:7474] can be kept alive indefinitely
2346 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection released: [id: 1][route: {}->http://localhost:7474][total kept alive: 1; route allocated: 2 of 10; total allocated: 2 of 10]
2350 [http-nio-8080-exec-4] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl  - committing
2350 [http-nio-8080-exec-4] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener  - Processing flush-time cascades
2350 [http-nio-8080-exec-4] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener  - Dirty checking collections
2350 [http-nio-8080-exec-4] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener  - Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
2350 [http-nio-8080-exec-4] DEBUG org.hibernate.event.internal.AbstractFlushingEventListener  - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
2350 [http-nio-8080-exec-4] DEBUG org.hibernate.internal.util.EntityPrinter  - Listing entities:
2350 [http-nio-8080-exec-4] DEBUG org.hibernate.internal.util.EntityPrinter  - com.Neo4jRestAPI.Person{firstname=Anna, gender=female, relationship_type=null, dob=10-10-1990, middlename=J, id=57, relationship=null, lastname=Smith}
2350 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection request: [route: {}->http://localhost:7474][total kept alive: 1; route allocated: 2 of 10; total allocated: 2 of 10]
2350 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection leased: [id: 1][route: {}->http://localhost:7474][total kept alive: 0; route allocated: 2 of 10; total allocated: 2 of 10]
2350 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.client.DefaultHttpClient  - Stale connection check
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.client.protocol.RequestAddCookies  - CookieSpec selected: best-match
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.client.protocol.RequestAuthCache  - Auth cache not set in the context
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.client.protocol.RequestProxyAuthentication  - Proxy auth state: UNCHALLENGED
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.client.DefaultHttpClient  - Attempt 1 to execute request
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.DefaultClientConnection  - Sending request: POST /db/data/transaction/54/commit HTTP/1.1
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "POST /db/data/transaction/54/commit HTTP/1.1[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "Accept: application/json[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "Accept-Encoding: gzip, deflate[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "Authorization: Basic bmVvNGo6Z2VuaXZpdHk=[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "X-Stream: true[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "Content-Length: 0[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "Host: localhost:7474[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "Connection: Keep-Alive[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  >> "[\r][\n]"
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> POST /db/data/transaction/54/commit HTTP/1.1
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> Accept: application/json
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> Accept-Encoding: gzip, deflate
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> Authorization: Basic bmVvNGo6Z2VuaXZpdHk=
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> X-Stream: true
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> Content-Length: 0
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> Host: localhost:7474
2352 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - >> Connection: Keep-Alive
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "HTTP/1.1 404 Not Found[\r][\n]"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Date: Tue, 03 Oct 2017 09:01:10 GMT[\r][\n]"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Content-Type: application/json[\r][\n]"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Access-Control-Allow-Origin: *[\r][\n]"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Content-Length: 178[\r][\n]"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "Server: Jetty(9.2.z-SNAPSHOT)[\r][\n]"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "[\r][\n]"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.DefaultClientConnection  - Receiving response: HTTP/1.1 404 Not Found
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << HTTP/1.1 404 Not Found
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Date: Tue, 03 Oct 2017 09:01:10 GMT
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Content-Type: application/json
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Access-Control-Allow-Origin: *
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Content-Length: 178
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.headers  - << Server: Jetty(9.2.z-SNAPSHOT)
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.client.DefaultHttpClient  - Connection can be kept alive indefinitely
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.wire  -  << "{"results":[],"errors":[{"code":"Neo.ClientError.Transaction.TransactionNotFound","message":"Unrecognized transaction id. Transaction may have timed out and been rolled back."}]}"
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection [id: 1][route: {}->http://localhost:7474] can be kept alive indefinitely
2354 [http-nio-8080-exec-4] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection released: [id: 1][route: {}->http://localhost:7474][total kept alive: 1; route allocated: 2 of 10; total allocated: 2 of 10]
2355 [http-nio-8080-exec-4] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl  - Initiating JDBC connection release from afterTransaction
18718 [Finalizer] DEBUG org.apache.http.wire  -  << "{"password_change_required":false,"password_change":"http://localhost:7474/user/neo4j/password","username":"neo4j"}"
18719 [Finalizer] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection [id: 0][route: {}->http://localhost:7474] can be kept alive indefinitely
18719 [Finalizer] DEBUG org.apache.http.impl.conn.PoolingClientConnectionManager  - Connection released: [id: 0][route: {}->http://localhost:7474][total kept alive: 2; route allocated: 2 of 10; total allocated: 2 of 10]

此外,我注意到的另一件事是,当我第一次发送JSON时,我会得到上面的日志。当我第二次发送它时,每行都会打印两次;当我第三次发送它时,每行都会打印三次,以此类推... 我不确定是什么原因导致了这个问题,但这可能是问题的原因。

在你的dao中,为什么要创建一个新的Person对象呢?你可以直接将参数中的person对象传递并持久化它。 - Vivek Singh
@VivekSingh 我正在遵循这个指南http://www.topjavatutorial.com/frameworks/hibernate/adding-hibernate-dao-layer-in-existing-maven-project/,它是用新对象的方式完成的。我从参数中传递了`person`对象,但我仍然得到“状态:200 OK”,并且对象没有保存。 - Porjaz
@pruntlar 是的,我已经刷新了数据库并且多次重启了它。 - Porjaz
请移除您的DAO中的try-catch块,以获取有意义的错误消息/堆栈跟踪。 - user3151902
请看异常的第一部分:LockClient[6511] <-[:HELD_BY]- RWLock[SCHEMA(0), hash=110596439] <-[:WAITING_FOR]- LockClient[6495],它说明客户端6495正在等待被客户端6511持有的锁。看起来多个客户端正在以无法被Neo4j解决的方式访问数据库。 - user3151902
显示剩余23条评论
4个回答

2

我通过将tomcat 8.5更换为wildfly 9来解决了我的问题。尽管所有其他操作都正常工作,但插入人员数据时出现了问题,至今我仍不确定 tomcat 的问题所在。


0

我猜测问题是

@GeneratedValue(strategy = GenerationType.AUTO)

无法找到适当的方法来创建密钥。 建议尝试类似这样的方式:
@SequenceGenerator(name = "sequence_generator_name", sequenceName = "sequence_name", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence_generator_name")

使用数据库序列来创建键。如果您不使用模式自动更新,则必须手动创建序列。语法细节取决于您的数据库。


那不是问题。我已经按照你建议的方式尝试过了,但最终结果仍然相同。无论哪种方式,都会在数据库中创建一个 SEQUENCE 对象,并具有属性:sequence_namenext_val。因此,即使我只使用 @GeneratedValue(strategy = GenerationType.AUTO),它也会自动使用 SEQUENCE 策略并创建 SEQUENCE 对象。 - Porjaz
对于误导,我很抱歉。 - Stas Shafeev

0

我认为我找到了错误,更改这些行:

em.persist(p);
em.flush();     
tx.commit();
em.clear(); 
em.close(); 
emf.close();

通过这些行:

em.persist(p);
em.flush();
em.close();
tx.commit();
emf.close();

我已经更改了它们,但不幸的是实体仍未保存。如果有帮助的话,我可以提供整个代码? - Porjaz
我忘记了 emf.close(),再试一次,永不放弃 :) - Halayem Anis
尝试过了,还是没有效果。我猜问题出在自动生成的ID上。正如帖子中提到的,如果我删除注释并手动指定ID,则实体将被保存。此外,当我使用本地查询保存实体(并在查询中指定ID)时,实体也会被保存。 - Porjaz
你在数据库中创建了一个序列吗? - Halayem Anis
是的,当我使用@GeneratedValue(strategy = GenerationType.AUTO)时,序列会自动在数据库中创建,并具有属性:sequence_namenext_val。因此,我认为这很好运行,因为日志显示已执行的查询以及生成的ID也在那里。 - Porjaz

0

替换这个:

catch ( Exception e ) {
    e.printStackTrace();
}

使用这个:

catch ( Exception e ) {
    throw new RuntimeException(e);
}

异常没有被重新抛出,因此就你的REST层而言,PersonDAO.addPerson已成功,并且它将生成一个OK响应。


当我替换catch块时,在get中只会得到以下堆栈跟踪信息:log4j:WARN No appenders could be found for logger (org.jboss.logging)。 log4j:WARN Please initialize the log4j system properly. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. - Porjaz
好的,看起来你报告的原始问题(关于状态200的问题)已经通过我的建议解决了。现在你又发现了另一个问题;你应该发布另一个问题,以免污染这个问题。 - Martín Straus
实际上问题还没有解决。我仍然无法将对象保存到数据库中。我在我的catch块中得到了与您建议的相同的堆栈跟踪。 - Porjaz
好的,你编辑了你的问题并在之后添加了另一半的问题,所以...无论如何,我不能帮你解决Neo4j的问题。你添加的堆栈跟踪似乎没有来自Neo4j的任何错误消息,除了关于事务的消息,而那个似乎是结果,而不是原因。如果根本错误被隐藏起来,你可能需要添加更多的日志记录。 - Martín Straus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接