CASCADE.ALL не работает

312
19 июля 2017, 22:33

У меня есть 2 Entity. Product и User:

@Entity
@Table(name="users")
public class User {
    @Id @GeneratedValue
    @Column(name="id")
    private int id;
    @Column(name="login")
    private String login;
    @Column(name="email")
    private String email;
    @Column(name="password")
    private String password;
    @Column(name="mobilePhone")
    private String mobilePhone;
    @Column(name="firstName")
    private String firstName;
    @Column(name="secondName")
    private String secondName;
    @Column(name="address")
    private String address;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "customer")
    private List<Product> cart;
//гетери и сетери
}

Product:

@Entity
@Table(name = "products")
public class Product {
    @Id @GeneratedValue
    @Column(name="id")
    private int product_id;
    @Column(name="name")
    private String name;
    @Column(name="descr")
    private String descr;
    @Column(name="price")
    private int price;
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User customer;
//гетери сетери
}

И есть класс которий тестит:

public class ProductServiceTest extends AbstractServiceTest{
    @Autowired
    private ProductService productService;
    @Autowired
    private UserService userService;
    @Test
    public void runTest(){
        User user = userService.get("AnotherLogin").get(0);
        Product product = new Product();
        product.setName("Test");
        product.setDescr("Test");
        product.setPrice(10101010);
        user.getCart().add(product);
        userService.update(user);
    }
}

Если я хочу получить список Product, которие принадлежат User, все работает нормально. Но когда я запускаю етот тест, то обьект product просто пропадает, и в бд не попадает, тоже и з удалением, апдейтом.

[UPDATE] Git репозиторий: https://github.com/OlegHudyma/Medical_WebSite

Answer 1

Классы-сущности:

@Entity
@Table(name="users")
public class User {
    @Id @GeneratedValue
    @Column(name="id")
    private int id;
    @OneToMany(cascade = CascadeType.ALL, 
               fetch = FetchType.LAZY, 
               mappedBy = "customer",
               orphanRemoval = true //для удаления элемента в removeTest
               )
    private List<Product> cart;
//гетеры, сетеры, другие поля
}
@Entity
@Table(name = "products")
public class Product {
    @Id @GeneratedValue
    @Column(name="id")
    private int product_id;
    @ManyToOne(fetch = FetchType.LAZY
               //тут не нужно cascade, иначе будет рекурсивное удаление
               //,cascade = CascadeType.ALL 
               )
    @JoinColumn(name = "user_id")
    private User customer;
//гетеры, сетеры, другие поля
}

Класс с тестом должен выглядеть примерно так:

public class ProductServiceTest extends AbstractServiceTest{
    @Autowired
    private SessionFactory sessionFactory;
    @Test
    public void addTest() {
        Session currentSession = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = currentSession.beginTransaction();
            User user = currentSession.createQuery("from User", User.class).getResultList().get(0);
            Product product = new Product();
            product.setName("Test3");
            product.setCustomer(user);
            //в рамках сессии добавили продукт
            user.getCart().add(product);
            //update не нужен, т.к. удаляем в hibernate транзакции
            //currentSession.update(user);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            currentSession.close();
        }
    }
//    Или так (то же самое, но выполняется внутри метода помеченного @Transactional)
//    @Transactional
//    public void addTest() {
//        User user = currentSession.createQuery("from User", User.class).getResultList().get(0);
//        Product product = new Product();
//        product.setName("Test3");
//
//        product.setCustomer(user);
//        //в рамках сессии добавили продукт, по окончании метода сохранится в БД
//        user.getCart().add(product);
//    }
    @Test
    public void removeTest() {
        Session currentSession = sessionFactory.openSession();
        Transaction tx = null;
        try {
            tx = currentSession.beginTransaction();
            User user = currentSession.createQuery("from User", User.class).getResultList().get(0);
            //удаляем первый элемент
            user.getCart().remove(0);
            //update не нужен, т.к. удаляем в hibernate транзакции
            //currentSession.update(user);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            currentSession.close();
        }
    }
//    Или так (то же самое, но выполняется внутри метода помеченного @Transactional)
//    @Transactional
//    public void removeTest() {
//        User user = currentSession.createQuery("from User", User.class).getResultList().get(0);
//        Product product = new Product();
//        product.setName("Test3");
//
//        product.setCustomer(user);
//        //в рамках сессии добавили продукт, по окончании метода сохранится в БД
//        user.getCart().add(product);
//    }    
}

Как видете из этих 2-х тестов, все добавляется и удаляется с помощью cascade = CascadeType.ALL. Почитайте как работает hibernate транзакции, и у Вас все будет получатся.

READ ALSO
Вывести числа на нечетных позициях

Вывести числа на нечетных позициях

Не могу разобраться с итераторами, здесь он выводит просто подряд числа, как сделать так, чтобы выводились числа, которые стоят на нечетной...

310
Работа с файлом на удаленке

Работа с файлом на удаленке

Selenium + TestNG + Winium(Java)

251