Spring/기타 코드들

Spring + JPA 프로젝트 더미 데이터 만들기

연어조아 2021. 10. 5. 14:17
728x90

01. 연습환경

  • Spring Boot
  • Spring Web
  • H2 Database
  • JPA
  • java 11

02. 연습 Model

  • 유저 1 : 게시판 n
  • 게시판 1 : 댓글 n
  • 유저 1 : 댓글 n
  • 관계이다.

User.java

@Entity
@NoArgsConstructor
public class User {

    // ID가 자동으로 생성 및 증가합니다.
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    // nullable: null 허용 여부
    // unique: 중복 허용 여부 (false 일때 중복 허용)
    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    @Enumerated(value = EnumType.STRING)
    private UserRoleEnum role;

    @Column(unique = true)
    private Long kakaoId;


    @BatchSize(size = 100)
    @OneToMany(mappedBy = "user", fetch = LAZY, cascade = ALL)
    private Set<Board> boards = new HashSet<>();

    @BatchSize(size = 100)
    @OneToMany(mappedBy = "user", fetch = LAZY, cascade = ALL)
    private Set<Comment> comments = new HashSet<>();
}

Board.java

@Setter
@Getter
@Entity
@NoArgsConstructor
public class Board extends Timestamped {

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String title;

    private String content;

    private String writer;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "member_id")
    @JsonIgnore
    private User user;

    @BatchSize(size = 100)
    @OneToMany(mappedBy = "board", fetch = LAZY, cascade = ALL)
    private Set<Comment> comments = new HashSet<>();
}

Comment.java

@Entity
@Getter
@NoArgsConstructor
public class Comment extends Timestamped {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String contents;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "board_id")
    @JsonIgnore
    private Board board;

    @ManyToOne(fetch = LAZY)
    @JoinColumn(name = "user_id")
    @JsonIgnore
    private User user;
}

03. SimpleListner.java

@NoArgsConstructor
@Component
public class SimpleListener implements ApplicationListener<ApplicationStartedEvent> {

    @Autowired
    private EntityManagerFactory entityManagerFactory;
    @Autowired
    PasswordEncoder passwordEncoder;

    @Override
    @Transactional
    public void onApplicationEvent(ApplicationStartedEvent event) {
        EntityManager em = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = em.getTransaction();
        transaction.begin();

        User testUser1 = new User("슈가1", passwordEncoder.encode("123"), "sugar1@sparta.com", UserRoleEnum.USER);
        User testUser2 = new User("슈가2", passwordEncoder.encode("123"), "sugar2@sparta.com", UserRoleEnum.USER);
        User admin = new User("root", passwordEncoder.encode("asdf"), "root@sparta.com", UserRoleEnum.ADMIN);

        em.persist(testUser1);
        em.persist(testUser2);

        for(int i = 0; i <10; i++){
            Board newBoard = new Board("new title " + i, "new contents " + i,  "writer " + i, testUser1);

            em.persist(newBoard);


            for (int j = 0; j<2; j++){
                Comment newComment = new Comment("new comment " + i, newBoard, testUser2);
                em.persist(newComment);

            }

        }
        em.getTransaction().commit();

    }
}
  • implements ApplicationListener<ApplicationStartedEvent> 를 통하여 ApplicationLisner의 구현체를 만든다.
  • onApplicationEventApplicationStartedEvent를 이용하여 서버가 켜질 때 위 함수가 실행 되도록한다.
  • 미리 DI를 이용하여 EntityManager 객체와 유저 비밀번호를 Encoder하는 passwordEncoder를 통하여 데이터를 저장한다.
  • 여러 개의 데이터를 Commit 해야함으로 @Transcational 애노테이션을 이용한다.
  • 실행하기 싫다면 @component 애노테이션을 삭제해서 빈 등록을 하지 않으면 된다.

주의할 점은 jpa의 1:n 관계에서 저장할 때는 1의 데이터가 미리 db에 저장을 해주어야 한다.
따라서 순서는 User -> Board -> Comment 순으로 저장을 해주었다.
사실 위는 당연할 사실이다. 해당하는 게시글이 없는데 그 글에 댓글이 존재한다는 것은 이상하니까

결과

SimpleListner 실행된 Query 문
저장된 더미 데이터들