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=?
Grazie! È molto più chiaro di quanto non sia nella documentazione di JPA. –
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
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. –