Domanda

AGGIORNAMENTO:ESEMPIO PER CHIARIRE Ho intenzione di mettere un esempio di ciò che sta accadendo proprio per chiarire la situazione nel mio Spring + Hibernate applicazione.Immaginate che queste due entità (supponiamo getter e setter esiste troppo)

@Entity
public class Class1(){
  private Integer id;

  @OneToOne
  private Class2 object2;
}

@Entity
public class Class2(){
  private Integer id;

  @OneToOne
  private Class1 object2;
}

Quindi nel mio database ho due tabelle una mappa di ogni istanza di ogni oggetto.Supponiamo che io sono memorizzati nel database di questi oggetti:

  • objectA (classe Class1) :id = 1 , oggetto2 = objectB
  • objectB (classe Class2) :id = 2 , oggetto2 = objectA
  • objectC (classe Class2) :id = 3 , oggetto2 = null il che significa che Un anb B sono collegate.Supponiamo ora voglio collegare objectA per objectC.Vuol dire che devo cancellare il link nel objectB troppo.

Per fare questo non fare le seguenti dosi:

//I get the objectA from database
Class1 storedObjectA = myservice.find(objectAId);
//Now in storedObject1 I have the same as what it is stored as objectA

//I change only the object2 attribute of it
storedObject1.setObject2(objectC);

//I search again in the database to see objectA
Class1 reStoredObjectA = myservice.find(objectAId);

restoredObjectA ora è:

  • restoredObjectA (class = Class1) id = 1, oggetto2 = objectC

se nel database c'è:

  • restoredObjectA (class = Class1) id = 1, oggetto2 = objectB

Il metodo di trovare non cercare nel database e ho acquistato la ricerca precedente anche se ho la mia query e secondo livello di cache disabilitata.Il metodo di trovare solo al DAO dove esegue la entityManager.trovare(Class1.class, id) Come posso fare il mio secondo trovare ricerca nel database?

Grazie


(Spiegazione)

Ciao,

Ho un'applicazione che utilizza la Primavera 3 e Hibernate.Ho un'entità chiamata Class1 che è memorizzato in un database.Questa entità ha un OneToOne link ad un altro soggetto chiamato Class2.Class2 ha un altro OneToOne Link a Class1, e entrambi i collegamenti sono uniche proprietà è impostata su true.

Ho il seguente codice nel mio controller:

//I have an object called dataFromUser which is instance of Class1 and
// it is obtained via @ModelAttribute annotation from a form

Integer id = dataFromUser.getId();

//I get correctly the stored object from the database
Class1 storedData = myService.find(id); //this will call em.find of hibernate

//I set to the stored data the attribute I want to change
storedData.setObject2();

//I save again the object
myService.save(storedData);

Il metodo salva in myService utilizzare il gestore di entità per rendere persistenti i dati, ma prima che controllerà la precedente associazione tra oggetto di Class1 e Class2 oggetto da eliminare nel caso di un nuovo Oggetto di Class2 è impostato su istanza di Class1.Per questo motivo ho per chiamare un metodo di ricerca di nuovo per vedere cosa c'è nel mio database

Nel Servizio:

@Transactional
public void save(Class1 object1){
   Class1 objectFromDB =  myDAO.find(object1.getId());
   // ....  update the old object and save
}

Il problema è che objectFromDB il Servizio non è lo stesso di quando ho fatto myService.trovare(id) nel controllore.Il problema è che non è cercare nel database, ma è la ricerca in memoria.Io lo so perché non c'è nessuna istruzione SQL è registrato quando il secondo metodo find() viene chiamato.Come avevo fatto setObject2() sul storedData oggetto è possibile ottenere esattamente questo oggetto quando chiamo trovare il metodo per la seconda volta, e il database non contiene questo perché non è stato persistente di sicurezza.

Ho provato a disabilitare la Cache nella mia configurazione solo per provare, ma è ancora accadendo.Ho un ehCache con questa configurazione:

In persistence.xml ho questa proprietà (io l'ho impostato a false entrambe le cache):

    <properties>
     <!-- Hibernate 3.5.0 - try org.hibernate.cache.* package -->
  <property name="hibernate.cache.provider_class"
               value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
   <property name="hibernate.cache.use_query_cache" value="false" />
  <property name="hibernate.cache.use_second_level_cache" value="false" />
  <property name="hibernate.generate_statistics" value="true" />
  <property name="hibernate.cache.use_structured_entries" value="false" />
  <property name="hibernate.format_sql" value="true" />
  <!-- http://www.jroller.com/eyallupu/entry/hibernate_s_hbm2ddl_tool -->
  <!-- create, create-drop, update, validate -->
  <property name="hibernate.hbm2ddl.auto" value="update" />
    </properties>  

Nel mio ehcache.xml ho impostato a 0 maxElementsInMemory e overflowToDisk a false per disabilitare troppo.

C'è un modo per evitare questa situazione?

Grazie.

È stato utile?

Soluzione 2

OK, per me è out.Il problema è che la sospensione cerca gli oggetti nella sua Sessione prima di eseguire la ricerca nel database.ho avuto modo indipendente l'oggetto della sessione prima di modificarlo.Per farlo in modalità di ibernazione:

    //being em my EntityManager instance
    Session session = (Session) em.getDelegate();
    session.evict(plan); 
    //Now the find object will not get the object wich is in session 
    //but the one in database

Altri suggerimenti

Non sono sicuro di aver capito bene, ma solo nel caso ...


Ci sono due metodi per caricare un oggetto.C'è una differenza se l'oggetto non è nell'attuale contesto di memoria:

  • Uno va di sicuro al database, restituisce l'istanza, se presente, o null in caso contrario.
  • L'altro si limita a creare un Proxy con l'id corretto, senza andare subito al database, e come richiesto in operazioni successive (probabilmente quando vampate di calore).

Sembra che si stia utilizzando la seconda, forse si potrebbe provare la prima e vedere se si risolve il problema?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top