2014-07-17 18 views
6

sto studiando JPA Documentazione e incontrate seguenti righe:PessimisticLockScope.NORMAL e di chiusura "relazioni"

relazioni di entità per i quali l'entità bloccato contiene la chiave esterna saranno bloccati, ma non lo stato del entità di riferimento (a meno che tali entità non siano esplicitamente bloccate). Raccolte di elementi e relazioni per le quali l'entità non contiene la chiave esterna (come le relazioni associate alle tabelle di join o alle relazioni uno-a-dire unidirezionali per le quali l'entità di destinazione contiene la chiave esterna) non saranno bloccate per impostazione predefinita.

è da here (PessimisticLockScope.NORMAL)

mi chiedo come interpretare queste linee. Se PessimisticLockScope è impostato su EXTENDED poi righe in tabelle di unirsi bloccata anche (ma non relative entità stesse), in modo da quando si utilizza NORMAL valore quello che sarà bloccato? Di sicuro fila entità (o righe se la strategia di successione è JOINED o TABLE_PER_CLASS o se ha un SecondaryTable), ma cosa significa "relazioni di entità":

relazioni di entità per i quali l'entità bloccato contiene la chiave esterna sarà anche bloccato

nel contesto di PessimisticLockScope.NORMAL?

risposta

4

relazioni di entità vengono associati ai database di associazioni FK.

Il PessimisticLockScope.NORMAL emetterà un blocco esclusivo del database molto aggressivo:

  • dell'entità dissociata righe della tabella
  • in una struttura di ereditarietà tabella unita sia la tabella di base e la tabella sottoclasse stanno per essere bloccato
  • tutti @ManyToOne e @OneToOne righe della tabella associate che hanno un rapporto effettivo FK (ad esempio il lato con @JoinColumn). Ma significa che non puoi modificare le informazioni FK, ovvero non puoi impostarlo su null o su qualsiasi altro valore diverso. Pertanto, solo il valore della colonna FK è bloccato, non l'altra tabella FK associata alla tabella.

Il @OneToMany, @ManyToMany e non proprietario @OneToOne e @ManyToOne associazioni non stanno per essere bloccato per queste associazioni hanno solo un equivalente Object-Oriented e il bloccaggio avviene esclusivamente a livello di database. Per ulteriori dettagli, controlla anche this article.

Il PessimisticLockScope.EXTENDED si espanderà per le associazioni @OneToMany e @ManyToMany troppo. Ma ancora una volta, questo si applica solo ai valori delle colonne FK non alle righe intere. Pertanto, questo blocco impedirà l'aggiunta/rimozione di elementi alle/dalle associazioni @OneToMany/@ManyToMany. Non impedisce l'aggiornamento degli elementi contenuti. Per questo, dovrai bloccare ciascuna entità contenuta.

+0

Grazie! È molto più chiaro di quanto non sia nella documentazione di JPA. –

+0

Bella spiegazione @Vlad. Puoi spiegare un po 'di più su "questo si applica solo ai valori delle colonne FK non alle righe intere". Intendi solo una colonna bloccata anziché una riga. Come viene tradotto questo blocco nel database. AFAIK, la granularità di un blocco è riga e colonna non OR questo blocco di rapporto è solo nella memoria. – Shailendra

+1

mi riferivo alla riga contenente l'FK (e in effetti il ​​blocco viene preso per tutta la fila, non solo una singola colonna) non la riga a cui fa riferimento la colonna FK. –

2

Qui ci sono alcuni esperimenti per quanto riguarda la questione. Sto usando Hibernate 4.3.6 come provider JPA e MySQL 5.6 come database.

poche entità di prova - Testperson, TestUser, TestOrder

TestUser estende Testperson (con l'ereditarietà RIUNITE) e TestUser ha una lista OneToMany bidirezionale dei TestOrders

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public class TestPerson { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long id; 

    private String name; 
    private String address; 

    //getters and setters 



@Entity 
public class TestUser extends TestPerson { 

    @OneToMany(fetch=FetchType.LAZY,mappedBy="user") 
    private List<TestOrder> orders ; 

    //getters and setters 


@Entity 
public class TestOrder { 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long id; 

    @ManyToOne 
    @JoinTable(name="test_user_orders") 
    private TestUser user; 

    private String orderNumber ; 

    //getters and setters** 

dati codice di creazione:

  em.getTransaction().begin();    
     TestUser user = new TestUser(); 
     user.setName("TestUser"+System.currentTimeMillis()); 
     user.setAddress("TestUserAddress1"); 
     em.persist(user); 
     List<TestOrder> orders = new ArrayList(); 
     for (int i=1;i<6;i++){ 
     TestOrder order = new TestOrder(); 
     order.setOrderNumber("ON"+System.currentTimeMillis()); 
     order.setUser(user); 
     em.persist(order); 
     orders.add(order); 
     } 
     user.setOrders(orders); 

     em.getTransaction().commit(); 
     em.close(); 




mysql> select * from test_person; 
+----+------------------+-----------------------+ 
| id | address   | name     | 
+----+------------------+-----------------------+ 
| 1 | TestUserAddress1 | TestUser1406031063539 | 
+----+------------------+-----------------------+ 
1 row in set (0.00 sec) 


mysql> select * from test_user; 
+----+ 
| id | 
+----+ 
| 1 | 
+----+ 


mysql> select * from test_order; 
+----+-----------------+ 
| id | order_number | 
+----+-----------------+ 
| 1 | ON1406031063627 | 
| 2 | ON1406031063673 | 
| 3 | ON1406031063678 | 
| 4 | ON1406031063683 | 
| 5 | ON1406031063686 | 
+----+-----------------+ 



mysql> select * from test_user_orders; 
+------+----+ 
| user | id | 
+------+----+ 
| 1 | 1 | 
| 1 | 2 | 
| 1 | 3 | 
| 1 | 4 | 
| 1 | 5 | 
+------+----+ 

ora sta facendo una ricerca per MnayToOne lato cioè, TestOrder

Map<String, Object> map = new HashMap<String, Object>(); 
map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED); 
TestOrder order = em2.find(TestOrder.class, new Long(1), LockModeType.PESSIMISTIC_WRITE, map); 

nota la "aggiornamenti" nella query per blocco pessimistico. Questa query include anche la tabella di join.

select 
     testorder0_.id as id1_8_0_, 
     testorder0_.order_number as order_nu2_8_0_, 
     testorder0_1_.user as user1_11_0_ 
    from 
     test_order testorder0_ 
    left outer join 
     test_user_orders testorder0_1_ 
      on testorder0_.id=testorder0_1_.id 
    where 
     testorder0_.id=? for update 

Hibernate: 
    select 
     testuser0_.id as id1_9_0_, 
     testuser0_1_.address as address2_9_0_, 
     testuser0_1_.name as name3_9_0_ 
    from 
     test_user testuser0_ 
    inner join 
     test_person testuser0_1_ 
      on testuser0_.id=testuser0_1_.id 
    where 
     testuser0_.id=? 

Anche quando interrogo per l'utente, questa volta solo le tabelle coinvolte nella gerarchia utente sono bloccati da "per l'aggiornamento"

Map<String, Object> map = new HashMap<String, Object>(); 
     map.put("javax.persistence.lock.scope", PessimisticLockScope.EXTENDED); 
     TestUser user = em2.find(TestUser.class, new Long(2), LockModeType.PESSIMISTIC_WRITE,map); 
     user.getOrders().size(); // to force initialization of orders 

Lo SQL risultante è:

 select 
     testuser0_.id as id1_9_0_, 
     testuser0_1_.address as address2_9_0_, 
     testuser0_1_.name as name3_9_0_ 
    from 
     test_user testuser0_ 
    inner join 
     test_person testuser0_1_ 
      on testuser0_.id=testuser0_1_.id 
    where 
     testuser0_.id=? for update 

Hibernate: 
    select 
     orders0_.user as user1_9_0_, 
     orders0_.id as id2_11_0_, 
     testorder1_.id as id1_8_1_, 
     testorder1_.order_number as order_nu2_8_1_, 
     testorder1_1_.user as user1_11_1_ 
    from 
     test_user_orders orders0_ 
    inner join 
     test_order testorder1_ 
      on orders0_.id=testorder1_.id 
    left outer join 
     test_user_orders testorder1_1_ 
      on testorder1_.id=testorder1_1_.id 
    where 
     orders0_.user=? 
+0

che è veramente buona spiegazione di ciò che 'EXTENDED' fa, ma la mia domanda è su' 'PessimisticLockScope.NORMAL' e relazioni di entità per i quali l'entità chiusa contiene la chiave esterna sarà anche locked' dichiarazione documentazione (posta sotto' valore NORMAL'). –