EclipseLink persistence and refresh both associati

2019-08-01 12:54发布

问题:

I'm using EclipseLink in my Java EE project with a PostgreSQL database. I have trouble finding the right annotations for a correct behaviour when I persist/refresh entities which are part of oneToMany/manytoOne associations.

For example, I have an entity "Project" which is first created by the users through a UI. Then the users can add "Analysis" into the project they created. Hence, an analysis is part of one project and a project can have several analysis. The persist action works fine (I see a new analysis associated with the project in my database) but when I call "getProject(idProject)" and display the list of its analysis I don't get to see the refreshed list.

How should I do this ?

The current annotations are :

In Projet.java

   // bi-directional many-to-one association to Analyse
   @OneToMany(mappedBy = "projet", cascade = { CascadeType.ALL })
   private Set<Analyse> analyses;

In Analyse.java

  //bi-directional many-to-one association to Projet
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH})
@JoinColumn(name="id_projet", nullable=false)
private Projet projet;

The code to persist a new "analyse" :

public boolean insertAnalyse(Analyse analyse) {
    System.out.println("insertAnalyse");
    boolean success = true;
    fac = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
    em = fac.createEntityManager();

    try {
        em.getTransaction().begin();
        em.persist(analyse);
            em.getTransaction().commit();
    }

    catch (Exception ex) {
        em.getTransaction().rollback();
        System.out.println("*** Erreur in MeansDAO. insertAnalyse() : "
                + ex.getMessage());
        success = false;

    } finally {
        em.close();
    }

    return success;
}

The code to retrieve the current project by projectID :

   public Projet getProject(String p) {
    System.out.println("getProject");
    Projet project = null;

    fac = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
    em = fac.createEntityManager();

    try {
        em.getTransaction().begin();
        StringBuilder sql = new StringBuilder();

        Projet proj = em.find(Projet.class, Integer.parseInt(p));

        if (proj != null) {
            project = proj;
        }

    } catch (Exception ex) {
        em.getTransaction().rollback();
        System.out.println("*** Erreur in MeansDAO. getProject() : "
                + ex.getMessage());
    } finally {
        em.close();
    }

    return project;
}

Thanks in advance for your help!

回答1:

First of all, you should not need to refresh, if your code was correct. When you persist the analyse, if it is related to the project, then you should be setting the relationship both ways. My guess is you are not doing that. In JPA you are responsible for maintaining your relationships correctly.

See, http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Object_corruption.2C_one_side_of_the_relationship_is_not_updated_after_updating_the_other_side

The reason you are seeing the stale state of the relationship is (because you did not maintain both sides, but also) because EclipseLink maintains a shared cache by default. You can disable this,

See, http://wiki.eclipse.org/EclipseLink/FAQ/How_to_disable_the_shared_cache%3F

To refresh an object in JPA you need to call refresh() on it, or execute a Query or find() operation using the refresh query hint.

For more information on caching see, http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching