Sluimerstand: het uitvoeren van SQL-uniciteit zonder beperkingen

Ik ontwikkel een applicatie met behulp van Hibernate. Een van de velden die ik invoeg, moet uniek zijn in een tabel. Het probleem hierbij is dat het veld niet de primaire sleutel is en de onderliggende database geen "UNIEKE" beperkingen ondersteunt. Dus ik moet dit afdwingen in mijn applicatiecode.

Deze pseudocode is wat ik tot nu toe heb:

void insert(Data data) {

  beginTransaction();

  boolean exists = existsRecordWithName(data.name);

 //Line 7

  if (exists == false) {
    insertRecord(data);
  } else {
    display("Name already exists in database!");
  }

  commit();
}

But if two different processes where to insert data at the same time, and the two reached line number 7, they would think there is no other record at the database with the same name and they both would insert it -> the result is a duplicate.

Dus hoe kon ik op deze manier het unieke afdwingen? Als ik pure SQL zou gebruiken, zou ik proberen de tabel te vergrendelen, maar ik ben op zoek naar een oplossing op een hoger niveau met standaardfuncties van Hibernate, dus het zou blijven werken als ik ooit de backend zou veranderen.

Alle hulp wordt gewaardeerd!

1

2 antwoord

U kunt geen unieke beperkingen afdwingen met applicatiecode. Beperkingen zijn strikt genomen van toepassing op alle gebruikers. Wat u in de toepassingscode doet, is alleen van toepassing op gebruikers die die toepassingscode toevallig gebruiken. Beperkingen in toepassingscode zijn bijvoorbeeld niet van toepassing op DBA's of ontwikkelaars die een opdrachtregelprogramma of GUI-hulpprogramma gebruiken om toegang te krijgen tot de database.

Dat gezegd hebbende, ondersteunt een SQL DBMS gewoonlijk sloten en transacties. Als u uniciteit niet kunt afdwingen door een kolom uniek te verklaren, is uw volgende beste weddenschap om de tabel expliciet te vergrendelen en misschien uw wijzigingen in een serialiseerbare transactie in te pakken. Ik denk dat het vergrendelen van de tafel voldoende zou moeten zijn, maar ik ga geen weddenschappen maken op een systeem dat geen unieke beperkingen ondersteunt.

Welke dbms ondersteunt geen unieke beperkingen? Ik ben er vrij zeker van dat ik nooit zoiets heb gezien en ik begon bijna 30 jaar geleden met databases te werken.

1
toegevoegd
Ik probeerde mijn code in een serialiseerbare transactie te verwerken, maar er veranderde niets. Om zeker te zijn, maakte ik een kleine test met PostgreSQL en het resultaat was hetzelfde ... De query die ik gebruik om te controleren of een rij bestaat, is een eenvoudig select aantal (*) , dus ik denk dat het serialiseerbaar gedrag hier is hetzelfde als read-commited. Ah, de dbms die ik gebruik is een zeldzaam goed ding opgelegd door de eindgebruiker ;-)
toegevoegd de auteur user683887, de bron

u kunt vergrendeling ook gebruiken in slaapstand (LockMode), mits uw database dit ondersteunt, maar vergrendelen met invoegtoepassingen is lastig (hoe u iets vergrendelt dat nog niet bestaat). wat gebeurt er als je een unique = "true" doet voor deze entiteit? slaapt er een foutmelding dat het niet kan, of staan ​​er duplicaten toe? Ik ga ervan uit dat u de equals en hashcode-methoden correct heeft geïmplementeerd.

In je code-overzicht hierboven, zou je intern() de naam kunnen geven en een gesynchroniseerd blok om de code op de naam kunnen doen - dat zou kunnen werken.

0
toegevoegd
Ik krijg duplicaten na het instellen van uniqueConstraints in slaapstandtoewijzing (met annotaties). Uw oplossing voor het gebruik van een gesynchroniseerd blok kan de slag maken, maar ik laat het aan het laatste redmiddel ;-)
toegevoegd de auteur user683887, de bron
eigenlijk, zelfs dat zou alleen werken op een enkele JVM, als je een geclusterde opstelling hebt, kun je nog steeds een probleem hebben.
toegevoegd de auteur aishwarya, de bron