Wat is het verschil tussen session.persist() en session.save() in Hibernate?

Kan iemand mij vertellen wat het voordeel is van persist()versus save()in Hibernate?


Antwoord 1, autoriteit 100%

Van dit forumbericht

persist()is goed gedefinieerd. Het maakt een
tijdelijke instantie persistent.
Het garandeert echter niet dat de
identifier-waarde wordt toegewezen aan
de aanhoudende instantie onmiddellijk,
de opdracht kan gebeuren bij flush
tijd. De specificatie zegt dat niet, wat
is het probleem dat ik heb met persist().

persist()garandeert ook dat het zal
voer een INSERT-instructie niet uit als het
wordt buiten de transactie genoemd
grenzen. Dit is handig bij
langdurige gesprekken met een
uitgebreide sessie/persistentie-context.

Een methode zoals persist()is vereist.

save()garandeert niet hetzelfde, het is
geeft een identifier terug, en als een
INSERT moet worden uitgevoerd om de
identifier (bijv. “identiteit” generator,
niet “reeks”), deze INSERT gebeurt
onmiddellijk, ongeacht of u dat bent
binnen of buiten een transactie.
Dit is niet goed op lange termijn
gesprek met een uitgebreide
Context van sessie/persistentie.


Antwoord 2, autoriteit 50%

Ik heb goed onderzoek gedaan naar save() vs. persist() inclusief het meerdere keren uitvoeren op mijn lokale computer. Alle voorgaande verklaringen zijn verwarrend en onjuist. Ik vergelijk save() en persist() methoden hieronder na grondig onderzoek.

save()

  1. Retourneert gegenereerde ID na opslaan. Het retourtype is Serializable;
  2. Slaat de wijzigingen in de database op buiten de transactie;
  3. Wijst de gegenereerde id toe aan de entiteit die u aanhoudt;
  4. session.save()voor een losgemaakt object zal een nieuwe rij in de tabel maken.

persist()

  1. Retourneert geen gegenereerde ID na opslaan. Het retourtype is void;
  2. Slaat de wijzigingen niet op in de database buiten de transactie;
  3. Wijst de gegenereerde ID toe aan de entiteit die u aanhoudt;
  4. session.persist()voor een losgemaakt object zal een PersistentObjectExceptiongenereren, aangezien dit niet is toegestaan.

Al deze zijn uitgeprobeerd/getest op Hibernate v4.0.1.


Antwoord 3, autoriteit 15%

Ik heb wat schijntesten gedaan om het verschil tussen save()en persist()vast te leggen.

Het lijkt erop dat beide methoden zich hetzelfde gedragen bij Transient Entity, maar verschillen bij detached Entity.

Neem voor het onderstaande voorbeeld EmployeeVehicle als een entiteit met PK als vehicleIdwat een gegenereerde waarde is en vehicleNameals een van de eigenschappen.

Voorbeeld 1: Omgaan met voorbijgaande objecten

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

Resultaat:

select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

Merk op dat het resultaat hetzelfde is wanneer u een reeds bestaand object krijgt en het opslaat

EmployeeVehicle entity =  (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity);    -------> **instead of session.update(entity);**
// session.persist(entity);

Herhaal hetzelfde met persist(entity)en geeft hetzelfde resultaat met nieuwe ID (zeg 37, honda);

Voorbeeld 2: Omgaan met een losstaand object

// Session 1 
// Get the previously saved Vehicle Entity 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();
// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached object 
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();

Resultaat: u zou kunnen verwachten dat het voertuig met id: 36, verkregen in de vorige sessie, wordt bijgewerkt met de naam “Toyota”. Maar wat er gebeurt, is dat een nieuwe entiteit in de DB wordt opgeslagen met een nieuwe ID gegenereerd voor en Naam als “Toyota”

select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

Persistent gebruiken om losgekoppelde entiteit te behouden

// (ii) Using Persist()  to persist a detached
// Session 1 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();
// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();

Resultaat:

Exception being thrown : detached entity passed to persist

Het is dus altijd beter om Persist() te gebruiken in plaats van Save() omdat save zorgvuldig moet worden gebruikt bij het omgaan met Transient object .

Belangrijke opmerking: in het bovenstaande voorbeeld is de pk van voertuigentiteit een gegenereerde waarde, dus wanneer save() wordt gebruikt om een losgemaakte entiteit te behouden, genereert hibernate een nieuwe id om te blijven bestaan. Als deze pk echter geen gegenereerde waarde is, resulteert dit in een uitzondering die aangeeft dat de sleutel is geschonden.


Antwoord 4, autoriteit 9%

Deze vraagheeft enkele goede antwoorden over verschillende persistentiemethoden in Hibernate. Om uw vraag direct te beantwoorden, wordt met save() het insert-statement onmiddellijk uitgevoerd, ongeacht de transactiestatus. Het geeft de ingevoegde sleutel terug, zodat je zoiets als dit kunt doen:

long newKey = session.save(myObj);

Gebruik dus save() als u onmiddellijk een identifier nodig hebt die aan de persistente instantie moet worden toegewezen.

Met aanhouden () wordt de insert-instructie uitgevoerd in een transactie, niet noodzakelijkerwijs onmiddellijk. Dit heeft de voorkeur in de meeste gevallen.

Gebruik blijven bestaan ​​() Als u het inzetstuk niet nodig hebt om te gebeuren met de reeks met de transactie en u de ingevoegde sleutel niet nodig heeft.


Antwoord 5, Autoriteit 4%

Opslaan () – Aangezien de naam van de methode suggereert, kan Hibernate Save () worden gebruikt om entiteit op database te bewaren. We kunnen deze methode buiten een transactie oproepen. Als we dit gebruiken zonder transactie en we hebben cascading tussen entiteiten, dan wordt alleen de primaire entiteit opgeslagen, tenzij we de sessie spoelen.

Personen () – HEIBERNATE AFHAG is vergelijkbaar met opslaan (met transactie) en het voegt het entiteitsobject toe aan de aanhoudende context, dus eventuele verdere wijzigingen worden gevolgd. Als de objecteigenschappen worden gewijzigd voordat de transactie is gepleegd of wordt gespoeld, wordt het ook in de database opgeslagen.
Ook kunnen we de methode () alleen binnen de grens van een transactie gebruiken, dus het is veilig en zorgt voor eventuele gecascadeerde objecten.
Ten slotte blijft volhouden niets terug, dus we moeten het bestaande object gebruiken om de gegenereerde identificatiere te krijgen.


Antwoord 6, Autoriteit 4%

Basisregel zegt dat:

Voor entiteiten met gegenereerde identifier:

Opslaan (): het retourneert de identificatie van een entiteit onmiddellijk naast het aanhouden van het object. Dus een invoegvraagstuk wordt onmiddellijk ontslagen.

Personen (): het retourneert het persistente object. Het heeft geen dwang van het onmiddellijk retourneren van de identifier, dus het garandeert niet dat inzetstuk onmiddellijk zal worden afgevuurd. Het kan onmiddellijk een insert vuren, maar het is niet gegarandeerd. In sommige gevallen kan de query onmiddellijk worden afgevuurd terwijl het in andere kan worden afgevuurd bij Session Flush-tijd.

Voor entiteiten met toegewezen identifier:

Opslaan (): het retourneert de identificatie van een entiteit onmiddellijk. Aangezien de identifier al is toegewezen aan de entiteit voordat het opslaan, wordt het inzetstuk niet onmiddellijk ontslagen. Het wordt ontslagen op Sessie Flush-tijd.

volhouden (): hetzelfde als opslaan. Het vuurt ook het inzetstuk bij de spoeling.

Stel dat we een entiteit hebben die een gegenereerde identifier als volgt gebruikt:

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;
    @Column(name = "USER_NAME")
    private String userName;
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

Opslaan ():

   Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.save(user); // Query is fired immediately as this statement is executed.
    session.getTransaction().commit();
    session.close();

Personen ():

   Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.persist(user); // Query is not guaranteed to be fired immediately. It may get fired here.
    session.getTransaction().commit(); // If it not executed in last statement then It is fired here.
    session.close();

Stel nu dat we dezelfde entiteit als volgt hebben gedefinieerd zonder dat het id-veld annotaties heeft gegenereerd, d.w.z. de ID wordt handmatig toegewezen.

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    private int userId;
    @Column(name = "USER_NAME")
    private String userName;
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

voor opslaan() :

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user); // Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

voor persist() :

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user); // Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

De bovenstaande gevallen waren waar wanneer het opslaan of volhouden werd aangeroepen vanuit een transactie.

De andere punten van verschil tussen opslaan en volhouden zijn:

  1. save() kan buiten een transactie worden aangeroepen. Als toegewezen identifier wordt gebruikt, aangezien id al beschikbaar is, wordt er dus geen insert-query onmiddellijk geactiveerd. De query wordt alleen geactiveerd wanneer de sessie wordt leeggemaakt.

  2. Als de gegenereerde identifier wordt gebruikt, wordt insert onmiddellijk geactiveerd, aangezien id moet worden gegenereerd. Maar het slaat alleen de primaire entiteit op. Als de entiteit enkele gecascadeerde entiteiten heeft, worden deze op dit moment niet in db opgeslagen. Ze worden opgeslagen wanneer de sessie wordt gewist.

  3. Als persist() buiten een transactie valt, wordt insert alleen geactiveerd wanneer de sessie wordt leeggemaakt, ongeacht het type identifier (gegenereerd of toegewezen) dat wordt gebruikt.

  4. Als opslaan wordt aangeroepen via een permanent object, wordt de entiteit opgeslagen met een update-query.


Antwoord 7, autoriteit 4%

Hier zijn de verschillen die u kunnen helpen de voordelen van persistentie- en opslagmethoden te begrijpen:

  • Het eerste verschil tussen opslaan en volhouden is hun retourtype. De
    retourtype van persistente methode is ongeldig terwijl retourtype opslaan
    methode is een serialiseerbaar object.
  • De methode persist() garandeert niet dat de id-waarde dat ook doet
    onmiddellijk worden toegewezen aan de persistente status, kan de toewijzing
    gebeuren tijdens het doorspoelen.

  • De methode persist() voert geen insert-query uit als deze wordt aangeroepen
    buiten de transactiegrenzen. Terwijl de methode save() retourneert
    een identifier zodat een insert-query onmiddellijk wordt uitgevoerd om te krijgen
    de identifier, ongeacht of deze binnen of buiten een
    transactie.

  • De persist-methode wordt aangeroepen buiten de transactiegrenzen, het is
    nuttig bij langlopende gesprekken met een verlengde sessie
    context. Aan de andere hand is Save-methode niet goed in een langlopende
    gesprek met een uitgebreide sessiecontext.

  • Vijfde verschil tussen opslaan en aanhouden van methode in slaapstand:
    blijven bestaan ​​wordt ondersteund door JPA, terwijl opslaan alleen wordt ondersteund door
    Hibernate.

U kunt het volledige werkvoorbeeld zien vanaf de post Verschil tussen opslag- en aanhoudende methode in de hibernate


Antwoord 8, Autoriteit 3%

Hier is het verschil:

  1. Opslaan:

    1. retourneert de ID / identifier wanneer het object in de database wordt opgeslagen.
    2. zal ook opslaan wanneer het object wordt geprobeerd om hetzelfde te doen door een nieuwe sessie te openen nadat het is vrijstaand.
  2. PASSEN:

    1. retourneert u niet wanneer het object is opgeslagen in de database.
    2. zal PerstentObjectException gooien wanneer probeerde het vrijstaande object door een nieuwe sessie te redden.

Antwoord 9

Eigenlijk is het verschil tussen HIBERNAIRE OPSLAAD () en PARECT () methoden afhankelijk van generatorklasse die we gebruiken.
Als onze generatorklasse is toegewezen, is er geen verschil tussen opslag () en volharding () methoden. Omdat generator ‘toegewezen’ betekent, als programmeur die we nodig hebben om de primaire sleutelwaarde te geven om op te slaan in de database RECHTS [Ik hoop dat u dit generatorenconcept weet]
Stel in het geval van een andere dan toegewezen generatorklasse, stel je aan als de naam van onze generatorklasse verhoging is, het overwinteren van de primaire sleutel-ID-waarde in de database-recht [anders dan toegewezen generator, SlaNNAlate alleen gebruikt om de primaire ID-waarde te verzorgen] Dus in dit geval als we opslaan () of blijvende () methode bellen, wordt het de record normaal in de database ingevoegd.
Maar hier is het ding, de methode opslaan () kan die primaire toets-ID-waarde retourneren die wordt gegenereerd door de winterslaap en we kunnen het bekijken
lange s = session.save (k);
In ditzelfde geval zal blijven bestaan ​​() nooit elke waarde terug naar de klant, retourtype leegte.
volhouden () garandeert ook dat het geen invoegverklaring zal uitvoeren als deze buiten de transactiegrenzen wordt genoemd.
Overwegende dat in SAVE () inzet onmiddellijk gebeurt, ongeacht of u binnen of buiten een transactie bent.


Antwoord 10

Het is volledig beantwoord op basis van het type “Generator” in ID tijdens het opslaan van entiteit.
Als waarde voor generator “toegewezen” is, wat betekent dat u de ID levert. Dan maakt het geen diff in de winterslaap voor opslaan of aanhouden. Je kunt gaan met elke gewenste methode. Als de waarde niet “toegewezen” wordt en u opslaan () gebruikt, krijgt u ID als rendement van de bewerking Opslaan ().

Nog een cheque is als u de bewerking buiten de transactielimiet of niet uitvoert of niet. Omdat aanhouden () behoort tot JPA tijdens het opslaan () voor overwinteren. Dus het gebruik ervan () buiten transactiegrenzen zullen het niet toestaan ​​om dat te doen en uitzondering te gooien met betrekking tot aanhoudende. Hoewel met opslaan () geen dergelijke beperking en één kan passen met DB-transactie door middel van opslaan () buiten de transactielimiet.

Other episodes