ManyToMany insert 과정에서 Error

ynoolee·2021년 9월 6일
0

게시판만들기

목록 보기
4/5

상황 : 게시판 만들기

  • User와 Role이 다대다 관계
  • JPA의 @ManyToMany 어노테이션을 사용
  • DB에는 중간테이블 "user_role"을 생성, 참조하는 각 테이블의 PK만을 이 테이블의 pk이자 fk로서 담고 있다.
  • 미리 role table에는 데이터를 하나 넣어놓았다.
insert roles values('1','ROLE_USER');
  • 코드에서는 User에 , 이 role을 setting 한 후, save 하는 것으로 작성 했다. (매우 간단한 버전.., 즉 모든 user가 하나의 ROLE로만 저장되는 )
    public User join(User user){
        // password 암호화
        String encodedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);
        System.out.println("encodedPassword = " + encodedPassword);
        // enabled 값 세팅
        user.setEnabled(true); 
        Role role = new Role();
        role.setId(1l);
        user.getRoles().add(role);
        return userRepository.save(user);
    }

DDL은 다음과 같다

create table users(
	id BIGINT auto_increment,
    username varchar(50) unique,
    password varchar(60),
    enabled BIT,
    primary key(id)
);
create table roles(
	id BIGINT auto_increment,
    name varchar(50),
    primary key(id)
);
create table user_role(
	user_id BIGINT,
    role_id BIGINT,
    primary key(user_id,role_id),
    foreign key (user_id) REFERENCES users(id),
    FOREIGN KEY (role_id) REFERENCES roles(id)
);

에러 살펴보기 -> 해결

Hibernate: insert into users (enabled, password, username) values (?, ?, ?)
Hibernate: insert into user_role (user_id, role_id) values (?, ?)
2021-09-06 21:40:21.659  WARN 30924 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 1452, SQLState: 23000
2021-09-06 21:40:21.659 ERROR 30924 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : Cannot add or update a child row: a foreign key constraint fails (`rest`.`user_role`, CONSTRAINT `FK859n2jvi8ivhui0rl0esws6o` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`))
2021-09-06 21:40:21.661  INFO 30924 --- [nio-8080-exec-2] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2021-09-06 21:40:21.696 ERROR 30924 --- [nio-8080-exec-2] 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 [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`rest`.`user_role`, CONSTRAINT `FK859n2jvi8ivhui0rl0esws6o` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`))
  • 참조 무결성 제약조건을 위반했다.
  • 그런데 에러가 난 부분이 이해가 되지 않는다. user에 insert를 먼저 하고, (role은 미리 db에 insert해 놓은 데이터가 있기 때문에 inser하지 않고), user_role에 insert를 하는데 user_role의 user_id가 user의 id를 reference하는 것에서 외래키 참조 무결성 제약조건 위반했다는 에러가 뜨고 있다.

원인: 알수 없는 Foreign keys

  • MySQL에서 DDL을 생성하고
  • user로 생성했다가 drop 후 users를 생성하고, users와 roles를 참조하는 user_role을 정의했다.

    그럼에도 user_role의 foreign keys를 확인하니

해결 : user_role을 재정의

create table user_role(
	user_id BIGINT,
    role_id BIGINT,
    primary key(user_id,role_id),
    foreign key (user_id) REFERENCES users(id),
    FOREIGN KEY (role_id) REFERENCES roles(id)
);

drop table user_role; 

0개의 댓글