Vra

Wat sou die maklikste manier om los'n spesifieke JPA Entiteit Bean wat verkry is deur middel van'n EntityManager.Alternatiewelik, kan ek het'n navraag terugkeer losstaande voorwerpe in die eerste plek sodat hulle sou in wese op te tree as "lees net'?

Die rede waarom ek wil om dit te doen is becuase ek wil om te verander die data binne die boontjie - met my aansoek nie, maar nie ooit het dit volgehou tot die databasis.In my program, ek het uiteindelik het om te bel spoel() op die EntityManager, wat sou voortduur al die veranderinge van aangeheg entiteite aan die underyling databasis, maar ek wil uitsluit spesifieke voorwerpe.

Was dit nuttig?

Oplossing

Ongelukkig, daar is geen manier om te ontkoppel een voorwerp van die entiteit bestuurder in die huidige JPA implementering, AFAIR.

EntityManager.duidelik() sal verbreek al die JPA voorwerpe, so dit is dalk nie'n geskikte oplossing in al die gevalle, as jy ander voorwerpe wat jy nie van plan om te bly verbind.

So is jou beste bet sal wees om te kloon die voorwerpe en slaag om die klone om die kode wat verander die voorwerpe.Sedert primitiewe en onveranderlike voorwerp velde is versorg deur die standaard kloning meganisme in'n behoorlike manier, sal jy nie het om te skryf'n baie van die loodgieter kode (afgesien van diep kloning enige saamgestelde strukture wat jy mag hê).

Ander wenke

(dalk te laat om te antwoord, maar kan nuttig wees vir ander wees)

Ek is die ontwikkeling van my eerste stelsel met JPA nou. Ongelukkig ek gekonfronteer met die probleem wanneer hierdie stelsel is byna voltooi.

Eenvoudig gestel. Gebruik Hibernate, of wag vir JPA 2.0.

In Hibernate, jy kan 'session.evict (voorwerp)' gebruik om 'n voorwerp van sessie te verwyder. In JPA 2.0, in die ontwerp nou , daar is die 'EntityManager.detach (voorwerp) 'n metode om 'n voorwerp losmaak van volharding konteks.

Dit maak nie saak wat JPA implementering jy gebruik, gebruik net entityManager.detach(object) dis nou in JPA 2.0 en deel van JEE6.

As jy nodig het om 'n voorwerp van die EntityManager los en jy gebruik Hibernate as jou onderliggende ORM laag kan jy toegang tot die Hibernate Sessie voorwerp en gebruik die Session.evict (voorwerp) metode wat Mauricio Kanada hierbo genoem.

public void detach(Object entity) {
    org.hibernate.Session session = (Session) entityManager.getDelegate();
    session.evict(entity);
}

Natuurlik is dit sal breek as jy oorgeskakel na 'n ander ORM verskaffer, maar ek dink dit is verkieslik om te probeer om 'n diep kopie maak.

Sover ek weet, die enigste direkte maniere om dit te doen is:

  1. Verbind die txn - Waarskynlik nie 'n redelike opsie
  2. Duidelike die Persistence Konteks - EntityManager.clear () - Dit is 'n wrede, maar sal dit duidelik uit
  3. Kopieer die voorwerp -. Die meeste van die tyd jou JPA voorwerpe is serialiseerbaar, so dit moet maklik wees (indien nie besonder doeltreffend)

As die gebruik van EclipseLink jy ook die opsies,

Gebruik die navraag wenk, eclipselink.maintain-cache"="false -. Al teruggekeer voorwerpe sal losstaande

Gebruik die EclipseLink JpaEntityManager copy() API om die voorwerp te kopieer na die verlangde diepte.

As daar nie te veel eienskappe in die boontjie, jy mag dalk net die skep van'n nuwe aanleg en al sy eiendomme hand van die volgehou bean.

Dit geïmplementeer kan word as'n afskrif constructor, byvoorbeeld:

public Thing(Thing oldBean) {
  this.setPropertyOne(oldBean.getPropertyOne());
  // and so on
}

Dan:

Thing newBean = new Thing(oldBean);

Dit is 'n vinnige en vuil, maar jy kan ook afleveringen en deserialize die voorwerp.

Sedert ek gebruik SEAM en JPA 1.0 en my stelsel het 'n fuctinality wat nodig het om al die velde veranderinge te meld, ek het 'n waarde voorwerp of data-oordrag voorwerp geskep as dieselfde velde van die entiteit wat moet aangemeld word. Die konstruktor van die nuwe POJO is:

    public DocumentoAntigoDTO(Documento documentoAtual) {
    Method[] metodosDocumento = Documento.class.getMethods();
    for(Method metodo:metodosDocumento){
        if(metodo.getName().contains("get")){
            try {
                Object resultadoInvoke = metodo.invoke(documentoAtual,null);
                Method[] metodosDocumentoAntigo = DocumentoAntigoDTO.class.getMethods();
                for(Method metodoAntigo : metodosDocumentoAntigo){
                    String metodSetName = "set" + metodo.getName().substring(3);
                    if(metodoAntigo.getName().equals(metodSetName)){
                        metodoAntigo.invoke(this, resultadoInvoke);
                    }
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

In JPA 1.0 (getoets met behulp van EclipseLink) jy kan die entiteit buite 'n transaksie te haal. Byvoorbeeld, met houer bestuur transaksies wat jy kan doen:

public MyEntity myMethod(long id) {
    final MyEntity myEntity = retrieve(id);
    // myEntity is detached here
}

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public MyEntity retrieve(long id) {
    return entityManager.find(MyEntity.class, id);
}

Doen deal met 'n soortgelyke geval het ek 'n DTO voorwerp wat die aanhoudende entiteit voorwerp strek geskep as volg:

class MyEntity
{
   public static class MyEntityDO extends MyEntity {}

}

Ten slotte, sal 'n skalaar navraag die verlangde nie daarin geslaag eienskappe te haal:

(Hibernate) select p.id, p.name from MyEntity P
(JPA)       select new MyEntity(p.id, p.name) from myEntity P

As jy hier kry, want jy eintlik wil 'n entiteit oor 'n afgeleë grens slaag dan kan jy net sit 'n paar kode in die hibernazi flous.

for(RssItem i : result.getChannel().getItem()){
}

Cloneable gewoond werk omdat dit eintlik afskrifte die PersistantBag oor.

En vergeet van die gebruik van serialiseerbaar en bytearray strome en op die fluit gespeel strome. die skep van drade te dooiepunte te vermy doodslaan die hele konsep.

Ek dink daar is 'n manier om 'n enkele entiteit van EntityManager sit deur te bel hierdie

EntityManagerFactory emf;
emf.getCache().evict(Entity);

Dit sal veral entiteit uit die kas te verwyder.

Ek dink jy kan metode EntityManager.refresh (Object o) ook gebruik as primêre sleutel van die entiteit het nie verander nie. Hierdie metode sal oorspronklike toestand van die entiteit te herstel.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top