3.4.5.3.2. Чтение и изменение данных во вложенной транзакции
Рассмотрим сначала зависимую вложенную транзакцию, создаваемую через getTransaction():
void methodA() {
    Transaction tx = persistence.createTransaction();
    try {
        EntityManager em = persistence.getEntityManager();
        Employee employee = em.find(Employee.class, id); (1)
        assertEquals("old name", employee.getName());
        employee.setName("name A"); (2)
        methodB(); (3)
        tx.commit(); (8)
    } finally {
      tx.end();
    }
}
void methodB() {
    Transaction tx = persistence.getTransaction();
    try {
        EntityManager em = persistence.getEntityManager(); (4)
        Employee employee = em.find(Employee.class, id); (5)
        assertEquals("name A", employee.getName()); (6)
        employee.setName("name B");
        tx.commit(); (7)
    } finally {
      tx.end();
    }
} 
  | 1 | загружаем сущность, где name == "old name" | 
| 2 | указываем новое значение для поля | 
| 3 | вызываем метод, создающий вложенную транзакцию | 
| 4 | получаем тот же экземпляр EntityManager, что и в methodA | 
| 5 | загружаем сущность с тем же идентификатором | 
| 6 | значение поля новое, так как мы работаем в том же persistent context, и запросов к БД не было | 
| 7 | commit в этот момент не происходит | 
| 8 | изменения сохраняются в БД, в них будет содержаться "name B" | 
Теперь рассмотрим тот же самый пример с независимой вложенной транзакцией, создаваемой через createTransaction():
void methodA() {
    Transaction tx = persistence.createTransaction();
    try {
        EntityManager em = persistence.getEntityManager();
        Employee employee = em.find(Employee.class, id); (1)
        assertEquals("old name", employee.getName());
        employee.setName("name A"); (2)
        methodB(); (3)
        tx.commit(); (8)
    } finally {
      tx.end();
    }
}
void methodB() {
    Transaction tx = persistence.createTransaction();
    try {
        EntityManager em = persistence.getEntityManager(); (4)
        Employee employee = em.find(Employee.class, id); (5)
        assertEquals("old name", employee.getName()); (6)
        employee.setName("name B"); (7)
        tx.commit();
    } finally {
      tx.end();
    }
} 
  | 1 | загружаем сущность, где name == "old name" | 
| 2 | указываем новое значение для поля | 
| 3 | вызываем метод, создающий вложенную транзакцию | 
| 4 | создаём новый экземпляр EntityManager, т.к. это новая транзакция | 
| 5 | загружаем сущность с тем же идентификатором | 
| 6 | значение поля старое, так как из БД загружен старый экземпляр сущности | 
| 7 | изменения сохраняются в БД, значение "name B" теперь будет храниться в БД | 
| 8 | из-за оптимистичной блокировки выбрасывается исключение, commit не выполняется | 
В последнем случае исключение в точке (8) возникнет, только если сущность является оптимистично блокируемой, т.е. если она реализует интерфейс Versioned.