DataIntegrityViolationException при сохранении сущности

0

Я пишу простое веб-приложение, используя Spring Boot и MySQL как базу данных. Код ниже

У меня есть объект Пользователь:

@Entity
@IdClass(UserKey.class)
public class User {

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Item> items;
    private String fullName;
    @Id
    private String principalId;
    @Id
    @Enumerated(EnumType.STRING)
    private LoginProvider loginProvider;
}

У меня также есть UserService:

@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    public User getCurrentUser() {
        try {
            return (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        } catch (Exception e) {
            return null;
        }
    }

    @Transactional
    public void addItemToUser(Item item) {
        User currentUser = getCurrentUser();
        if (!currentUser.getItems().contains(item)) {
            currentUser.getItems().add(item);
            userRepository.save(currentUser);
        }
    }
}

И контроллер:

@Controller
public class UserController {
PostMapping(value = "/addItem/{id}")
    @ResponseStatus(value = HttpStatus.OK)
    public void addItemToUser(Map<String, Object> model, @PathVariable int id) {
        userService.addItemToUser(itemService.getItem(id));
    }
}

Это мой класс Item:

@Entity
public class Item {

    @Id
    @GeneratedValue
    private int id;
    @Enumerated
    private Category category;


    public Item() {
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Item item = (Item) o;

        return id == item.id;
    }

    @Override
    public int hashCode() {
        return id;
    }
}

И это мой репозиторий:

public interface UserRepository extends CrudRepository<User, Integer> {}

Контроллер и все работают нормально, но иногда возникает следующая ошибка, когда я пытаюсь обновить список с помощью моих элементов:

    2018-04-03 17:09:53.814 ERROR 24265 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [PRIMARY]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '23942983472937-FACEBOOK-2' for key 'PRIMARY'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_121]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_121]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_121]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_121]
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.42.jar:5.1.42]
    at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.42.jar:5.1.42]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:935) ~[mysql-connector-java-5.1.42.jar:5.1.42]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3973) ~[mysql-connector-java-5.1.42.jar:5.1.42]
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3909) ~[mysql-connector-java-5.1.42.jar:5.1.42]
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527) ~[mysql-connector-java-5.1.42.jar:5.1.42]
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680) ~[mysql-connector-java-5.1.42.jar:5.1.42]
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2490) ~[mysql-connector-java-5.1.42.jar:5.1.42]

Как я могу избавиться от этой ошибки?

Теги:
spring-boot
spring-mvc
spring-data-jpa
spring-data

2 ответа

0

Попробуйте реализовать equals(Object obj) и hashCode() следующим образом:

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = (prime * result) + (int) id;
        result = (prime * result) + ((category == null) ? 0 : category.hashCode());

        return result;
    }

@Override
public boolean equals(final Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;

    final Item item = () obj;
    if (id != item.id)
        return false;
    if (!category.equals(item.category))
        return false;
    return true;
}

во все ваши классы UserKey, User, Item, Category, LoginProvider. А также попробуйте добавить эти аннотации к вашему элементу id:

@Column(unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO)

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

0

Это поможет, если вы разместите свой класс Item. Я предполагаю, что вам нужно реализовать методы equals(Object obj) & hashCode() чтобы ваш Set<Item> не имел дубликатов.

  • 0
    Я обновил свой вопрос. Методы hashCode и equals(Object object) уже реализованы. Может я ошибся?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню