简体   繁体   中英

JPA Not Maintaining Connections

So it looks like once the program ends, the object connections aren't persisted. Let me explain with a simple example:

//Adding a friend to person and "sending" that friend a message.

em.getTransaction().begin();

Friend person = new Friend();
person.setName("One");

Friend friend = new Friend();
friend.settName("Two");

Message messageToFriend = new Message();
messageToFriend.setMessage("Hi");

friend.getMessages().add(messageToFriend);

person.getFriends().add(friend);

em.persist(person);

em.getTransaction().commit();

//Test Code:

Query q = em.createQuery("select f from Friend f where f.name = 'One'");
List<Friend> personList = q.getResultList();

Friend retrievedPerson = personList.get(0);

System.out.println("Friend size: "+retrievedPerson.getFriends().size());
if(retrievedPerson.getFriends().size() > 0){
    List<Message> messagesToFriend = retrievedPerson.getFriends().get(0).getMessages();

    System.out.println("Friend message size: "+messagesToFriend.size());

    if(messagesToFriend.size() > 0){
        System.out.println("Message to "+retrievedPerson.getFriends().get(0).getName()+": "+messagesToFriend.get(0).getMessage());
    }
}

This will print just as expected:

Friend size: 1

Friend message size: 1

Message to Two: Hi

BUT once the program ends and I again try the test code:

Friend size: 0

If I do a query to get ALL friends, I get both friends: One and Two, but the connections between the two are gone. Even the Message on the Friend is gone (although it too is still in the database and querying for Messages gets the Message).

Why would the connections between the objects be getting lost?

I'm using MySQL and EclipseLink.

Additional Code:

 @Entity
    public class Friend {

        @Id
        @GeneratedValue(strategy = GenerationType.TABLE)
        public String id;

        private String name;

        @OneToMany(mappedBy="parentFriend", cascade = CascadeType.PERSIST)
        private List<Friend>friends = new ArrayList<Friend>();

        @ManyToOne
        private Friend parentFriend;

        @OneToMany(mappedBy="friend", cascade = CascadeType.PERSIST)
        private List<Message>messages = new ArrayList<Message>();

        public List<Message>getMessages(){
            return messages;
        }

        public List<Friend>getFriends(){
            return friends;
        }

        public String getName() {
            return name;
        }

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

    }

@Entity
public class Message {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private String id;

    @ManyToOne
    private Friend friend;

    private String message;

    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

You may need an em.flush() after the commit. JPA doesn't make guarantees about when the data is actually persisted to the database. I believe the em.flush() method will explicitly persist it, assuming you don't want to close the entity manager yet.

I'm sorry, after looking at your question again, I'm afraid I've answered incorrectly. I think the problem is because your code doesn't cross-link the friends and the parentFriend field. Your code should look more like:

Friend a = new Friend();
Friend b = new Friend();
a.getFriends().add(b);
b.setParentFriend(a);

Without both fields being set the linkage won't happen, even with the persist cascade.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM