728x90

public class Board {

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

@SequenceGenerator(sequenceName = "board_boardno_seq", name = "board_boardno_seq")

private Long boardno;

private String title;

private String writer;

private String content;

@ColumnDefault("sysdate")

@CreationTimestamp

private LocalDateTime regdate;

private Long readcount;

private Long groupno;

private Long step;

private Long depth;

}

@UpdateTimestamp도 있어서 update시 regdate에 time을 넣어줄 수 있지만 

CreationTimestamp와 중복하여 사용할 수 없다. 

사용하려면 updatedate 필드를 만들어서 붙여야 한다. 

 

@ColumnDefault 어노테이션은 jpa에서 insert할 때는 무시한다. 

하지만 sql을 사용할때는 적용되기 때문에 붙여준다. 

 

Repository

 

List<Board> findByStepGreaterThanAndGroupno(Long step,Long groupNo);

List<Board> findByBoardnoGreaterThanEqualOrderByGroupnoDescStepAsc(Long boardNo);

//Page<Board> findByBoardnoGreaterThanEqualOrderByGroupnoDescStepAsc(Long boardNo,Pageable pageable);

 

 

new_save() 새글 작성하기

void new_save() {

Board board1= Board.builder()

.title("게시판101")

.content("내용101")

.writer("101")

.build();

Board savedBoard1 = boardRepository.save(board1);

savedBoard1.setGroupno(savedBoard1.getBoardno());

savedBoard1.setStep(1L);

savedBoard1.setDepth(0L);

savedBoard1.setReadcount(0L);

savedBoard1= boardRepository.save(savedBoard1);

System.out.println(">>>savedBoard1:"+savedBoard1);

 

 

답글 작성

void reply_save() {

Board findBoard100 = boardRepository.findById(100L).get();

 

List<Board> updateBoardList100 =

boardRepository.findByStepGreaterThanAndGroupno(findBoard100.getStep(), findBoard100.getGroupno());

for (Board tempBoard : updateBoardList100) {

tempBoard.setStep(tempBoard.getStep()+1);

}

boardRepository.saveAll(updateBoardList100);

 

Board board101=Board.builder()

.title("게시판타이틀101")

.content("내용101")

.writer("김경호101")

.groupno(findBoard100.getGroupno())

.step(findBoard100.getStep()+1)

.depth(findBoard100.getDepth()+1)

.readcount(0L)

.build();

boardRepository.save(board101);

 

그룹넘버가 같고 step이 더 큰 글(답글을 달려는 원글의 답글들 , 원글이 답글이 될 수도 있다)에 step을 증가시킴 

board101 글을 원글보다 step, depth를 증가시키고 save 

 

void board_select() {

List<Board> boardList = boardRepository.findAll();

for (Board board : boardList) {

System.out.println(board);

}

boardList = boardRepository.findByBoardnoGreaterThanEqualOrderByGroupnoDescStepAsc(0L);

for (Board board : boardList) {

System.out.println(board);

}

 

글 목록 전체 조회 

list를 groupno 내림차순, step 오름차순으로 정렬하여 select 

orderBy 할때 앞에 조건문이 필요하여 BoardnoGreaterThanEqual 추가해주고 0L인자로 준다. 

 

 

페이징 작업

void board_select_page() {

List<Board> boardList=boardRepository.findAll();

System.out.println(">>>boardList:"+boardList.size());

 

int currentPage=14; //현재페이지

int size=7; //페이지당게시물수

 

Pageable pageable=PageRequest.of(currentPage-1,

size,

Sort.by("groupno").descending()

.and(Sort.by("step").ascending())

);

/*

PageRequest.of(page, size)

- page zero-based page index.(요청페이지)

- size the size of the page to be returned.(페이지당 게시물 수)

*/

Page<Board> page = boardRepository.findAll(pageable);

for (Board board : page.getContent()) {

System.out.println(board);

}

}

Pageable 인터페이스

 

  1. pageNumber: 페이지 번호를 나타냅니다. 0부터 시작하며 첫 번째 페이지는 0입니다. 이 속성은 몇 번째 페이지를 가져올지를 결정합니다.
  2. pageSize: 한 페이지에 표시될 항목 수를 나타냅니다. 예를 들어, 페이지당 10개의 항목을 표시하려면 pageSize를 10으로 설정합니다.
  3. offset: 페이지의 시작 항목의 오프셋입니다. 이것은 pageNumber * pageSize의 값과 같습니다. 데이터베이스 쿼리를 작성할 때 특정 페이지의 데이터를 가져오는 데 사용됩니다.
  4. sort: 페이지의 항목을 정렬하는 데 사용됩니다. Sort 타입의 객체로 정렬 방법과 정렬할 필드를 지정할 수 있습니다. 다음은 Sort를 사용하는 예입니다.이것은 "fieldName" 필드를 오름차순으로 정렬하는 방법을 나타냅니다.
    Sort sort = Sort.by(Sort.Order.asc("fieldName"));
  5. unpaged(): 페이지네이션을 사용하지 않고 모든 데이터를 한 번에 가져오도록 지정합니다. 주로 모든 데이터를 가져올 때 사용됩니다.
  6. next(): 다음 페이지로 이동하는 Pageable 객체를 생성합니다.
  7. previousOrFirst(): 이전 페이지로 이동하거나 첫 번째 페이지로 이동하는 Pageable 객체를 생성합니다.
  8. first(): 첫 번째 페이지로 이동하는 Pageable 객체를 생성합니다.
  9. hasNext(): 다음 페이지가 있는지 확인합니다.
  10. getSort(): 현재 페이지에 적용된 정렬 정보를 가져옵니다.

 

 

Pageable 인터페이스는 데이터베이스 조회 결과를 정렬하고 페이지를 나누고 그 페이징 관련 정보를 담고 있다. 

Pageable pageable=PageRequest.of(currentPage-1,

size,

Sort.by("groupno").descending()

.and(Sort.by("step").ascending())

);

PageRequest의 of (page,size)메서드를 사용하면 페이지를 전체 리스트를 size로 나누어 페이징했을 때 구한 page의 paging 정보를 Pageable 인터페이스로 반환해준다.

 

추가로 page,size, Sort(정렬)을 대입할 수도 있다. 

Sort.by("groupno").descending().and(Sort.by("step").ascending())

 

 

findAll 메서드에 Pageable을 인자로 대입하면 해당 Pageable의 Page를 반환해주고 

Page의 getContent 하여 리스트를 얻을 수 있다. 

반대로 Page에서 getPageable 을 하면 Pageable을 얻을 수 있다. 

 

 

  1. getContent(): 페이지에 포함된 데이터 항목들을 반환합니다. 이 메서드를 통해 현재 페이지의 데이터를 가져올 수 있습니다.
  2. getNumber(): 현재 페이지 번호를 반환합니다. 페이지 번호는 0부터 시작합니다.
  3. getSize(): 페이지 크기(한 페이지 당 항목 수)를 반환합니다.
  4. getTotalPages(): 전체 페이지 수를 반환합니다.
  5. getTotalElements(): 전체 항목 수를 반환합니다. 이는 모든 페이지를 합친 총 데이터 항목 수입니다.
  6. hasContent(): 페이지에 데이터가 포함되어 있는지 여부를 확인합니다.
  7. hasNext(): 다음 페이지가 있는지 여부를 확인합니다.
  8. hasPrevious(): 이전 페이지가 있는지 여부를 확인합니다.
  9. isFirst(): 현재 페이지가 첫 번째 페이지인지 여부를 확인합니다.
  10. isLast(): 현재 페이지가 마지막 페이지인지 여부를 확인합니다.
  11. nextPageable(): 다음 페이지로 이동하는 데 필요한 Pageable 객체를 반환합니다.
  12. previousPageable(): 이전 페이지로 이동하는 데 필요한 Pageable 객체를 반환합니다.

'Java > Spring Boot' 카테고리의 다른 글

Thymeleaf Layout  (1) 2023.11.24
JPA Object Relation Mapping  (0) 2023.10.11
Spring Data JPA begins  (0) 2023.10.06
Spring CRUD with RestAPI  (0) 2023.09.20
Spring addViewControllers  (0) 2023.09.14
728x90

프로그레스 배열이 주어지고 진행 속도 배열이 주어진다. 

프로그레스가 100이 되면 배포할 수 있는데 , 순서에 따라 배포할 수 있기 때문에 

앞의 프로그레스가 100이 되지 않으면 뒤의 프로그레스는 100이 되어보 배포될 수 없다. 

그래서 앞에서부터 순서대로 기능이 완성되어 배포할 때 한번에 여러개가 동시에 배포될 수 있다. 

매번 배포할 때마다 몇개의 완성된 기능이 배포되는지 반환 

 

일단 하루가 지나면 프로그레스의 모든 기능들은 스피드만큼 프로그레스가 증가한다. 

그리고 매일 프로그레스가 100이 넘었는지 확인해주고 넘었으면 다음 프로그레스도 함께 확인하고 

다음 프로그레스가 100이 아닌 것을 확인했을 때, 그때까지 100이 넘어 배포해야할 프로그레스의 개수를 list에 넣는다. 

 

for (int i = 0; i < speeds.length; i++) {

progresses[i] += speeds[i];

}

매일 모든 프로그레스가 스피드만큼 증가

 

if (progresses[j] >= 100) {

count++;

continue;

}

프로그레스가 100이 넘었는지 확인하고 넘었으면 배포할 개수 count를 증가시키고 다음 프로그레스도 확인한다. 

 

카운트가 0 이 아니라면 ( 배포해야할 순서의 프로그레스가 100이 넘었다면 ) list에 count를 추가하고 다시 카운트를 0으로 초기화한다. 

if (count != 0) {

answer.add(count);

count = 0;

}

 

 

 

전체풀이

public ArrayList<Integer> solution(int[] progresses, int[] speeds) {

ArrayList<Integer> answer = new ArrayList<Integer>();

int count = 0;

for (int j = 0; j < progresses.length; j++) {

if (progresses[j] >= 100) {

count++;

continue;

} else {

j--;

for (int i = 0; i < speeds.length; i++) {

progresses[i] += speeds[i];

}

}

if (count != 0) {

answer.add(count);

count = 0;

}

}

if (count != 0) {

answer.add(count);

}

return answer;

}

j를 감소시키는 이유는 프로그레스가 100이 넘지 않았는데 다음 프로그레스를 확인하면 안되기 때문에 다시 j를 감소시키고 하루가 지났다 가정하고 모든 프로그레스를 스피드만큼 증가시키고 재확인할 수 있게 해준다. 

 

마지막 남은 프로그레스가 100이 되면 count를 증가시킨 후  continue로 빠져나와 list에 추가하지 못하기 때문에 

for문을 빠져나온 후 한번더 list에 추가해준다. 

 

 

'Java > Coding Test' 카테고리의 다른 글

카펫 문제 풀이  (0) 2023.10.06
올바른 괄호 문제 풀이  (1) 2023.10.05
크레인 인형뽑기 게임 문제 풀이  (0) 2023.10.04
로또의 최고 순위와 최저 순위 문제 풀이  (0) 2023.10.04
다트 게임 문제 풀이  (0) 2023.10.04
728x90

배열 : 같은 데이터타입을 가진 저장소

- 배열은 객체이고 배열형의 변수는 저장소의 참조변수를 가진다.

- 배열은 같은 타입만 정의가 가능하다. 여러 타입의 데이터를 하나의 배열에 넣을 수 없다. 

- 배열의 길이는 고정되어있다. 

 

배열객체 변수의 선언 

Type[] identifier;

Type identifier[];

int[] intArray;

int intArray[];

배열객체의 초기화 

intArray = new int[5];

intArray[0] = 80;

intArray = new int[] {1,2,3,4,5};

객체를 원소로 가지는 배열의 초기화 

Account acc1 = new Account(1111, "LEE", 5600, 0.8);

Account[] accounts = {acc1,

new Account(2222, "KIM", 568000, 3.5),

new Account(3333, "PARK", 965000, 6.9)

};

 

 

배열 객체를 생성하면 초기값이 주어진다.

intArray  = new int[5];

// new int[5] 로 생성함과 동시에 intArray[0] ~intArray[4]까지 각 원소는 모두 0 으로 초기화된다.

정수형은 0

실수형은 0.0

논리형은 false

문자형은 공백

Object는 null로 초기화한다.

 

배열객체는 다음과 같은 멤버를 가지고 있으며 

length 변수를 통해 배열의 길이를 알아낼 수 있다.

배열의 활용

반복문 

for (int i = 0; i < rankArray.length; i++) {

totArray[i]=korArray[i]+engArray[i]+mathArray[i];

avgArray[i]=totArray[i]/3.0;

if(avgArray[i]>=90)

gradeArray[i]='A';

else if(avgArray[i]>=80)

gradeArray[i]='B';

else if(avgArray[i]>=70)

gradeArray[i]='C';

else if(avgArray[i]>=60)

gradeArray[i]='D';

}

728x90

http://projects.spring.io/spring-data/

 

Spring Data

Spring Data’s mission is to provide a familiar and consistent, Spring-based programming model for data access while still retaining the special traits of the underlying data store. It makes it easy to use data access technologies, relational and non-rela

spring.io

 

 

ORM object relation mapping

 

ORM은 자바 객체와 SQL DB의 테이블 사이의 맵핑 메타데이터를 사용하여

자바 객체를 SQL DB의 테이블에 자동으로 영속화해주는 기술 

 

객체를 릴레이션 테이블에 맵핑할 때 생기는 문제

- 밀도 granularity 문제 : 객체는 다양한 크기의 다양한 커스텀 객체를 만들기 쉬우나 릴레이션은 기본 타입만 사용할 수 있다. 

- 서브타입 subtype 문제 : 객체는 상속 구조를 만들기 쉽지만 릴레이션은 그렇지 못한다

- 식별성 identity 문제 : 객체를 동일한 객체로 인식할때 레퍼런스가 같은면 동일하다고 할지, 레퍼런스가 달라도 가지고 있는 멤버와 그 값이 동일할 때 같다고 할지에 대해서 정해줘야 하지만 릴레이션에서는 주키를 같으면 동일한 인스턴스로 본다.

- 관계 association 문제 : 객체는 방향성이 존재하고 다대다 맵핑이 가능하지만 릴레이션은 방향성이 존재하지 않고 외래키로 관계를 표현할 뿐이다.

- 데이터 네비게이션 navigation 문제 : 객체는 콜렉션을 순회하고 레퍼런스를 이용해 다른 객체로 이동도 가능하지만

릴레이션은 데이터베이스에 성능을 위해 적은 요청으로 여러 릴레이션에 접근하기 위해 join을 사용해야한다. 

 

스프링 데이터 

 

- 스프링 데이터 : SQL, NoSQL 저장소 지원

- 스프링 데이터 common : 여러 저장소 지원 프로젝트의 공통 기능 ( Repository > CrudRepository > PagingAndSortingRepository )

- 스프링 데이터 rest : 저장소의 데이터를 하이퍼미디어 기반 HTTP리소스로 제공

- 스프링 데이터 JPA : 스프링데이터 common이 제공하는 기능에 JPA 관련 기능 추가 ( JpaRepository )

 

 

 

 

 

 

 

 

JPA 실습

 

new Spring Starter Project 

DI 

spring data JPA

lombok

spring boot devTools

oracle JDBC

(JDBC API)

 

application.properties

Generic Editor로 열면 content assist 사용가능 

 

spring.datasource.url=jdbc:oracle:thin:@111.111.111.11:1521:xe

spring.datasource.username=j

spring.datasource.password=j

#테이블 자동 생성 옵션

spring.jpa.hibernate.ddl-auto=create

JPA는 구현체로 Hibernate를 사용한다.

 

#시작시 drop테이블시 error가 발생하면 멈춤

spring.sql.init.continue-on-error=false

 ddl create 작업 실행시 drop 후 create를 하는데 최초에는 table이 없기 때문에 drop시 오류가 발생하고 실행을 멈추는데 

실행이 멈추는 걸 막고 계속 실행하게 하는 설정 

 

#JPA sql 초기화 작업 user-insert.sql을 테이블이 drop-create 이후 자동으로 실행시켜줌

spring.sql.init.mode=always

spring.sql.init.data-locations=classpath:user-insert.sql,classpath:guest-insert.sql

#spring.sql.init.schema-locations=classpath:user.ddl

spring.sql.init 은 sql이 시작될때 바로 실행되는 작업을 뜻한다. 

나중에 테스트를 위해 sql insert 작업을 할 때 

insert.sql 파일로 다량의 sql 작업을 처리할 때 data-locations에 insert.sql 파일을 알려준다. 

sql 시작할때 테이블을 생성할 ddl 파일을 init으로 실행하기 위한 설정으로 schema-locations에 ddl 파일의 위치를 기술 

여기서는 hibernate.ddl-auto=true 설정을 하여 생략하였다.

 

spring.jpa.defer-datasource-initialization=truetrue로 설정해서 hibernate 초기화 이후 data.sql가 실행되도록 변경한다.

 hibernate 초기화 이후 sql이 실행되도록 지연시키는 설정 

 

spring 실행 로그

#SQL을 로그로 보여주는 옵션, 상세보기 옵션

spring.jpa.show-sql=true

spring.jpa.properties.hibernate.format_sql=true

 

logging.level.org.hibernate.orm.jdbc.bind=trace

쿼리에 binding 하는 파라메터를 보여줌 

 

 

 

 

 

 

 

 

entity 패키지 하위 UserEntity 클래스 생성

@Entity(name="user")

entity는 객체세상에서 table을 표현하는 이름으로 entity의 이름은 default로 클래스의 이름(소문자)로 설정되고 name property로 지정해 줄 수 있다. 

@Table(name="userinfo")

table은 Relation에서의 table 이름으로 대부분의 DB에서는 user를 예약어로 사용하므로 user를 사용하지 못한다.

 

@Id

private String userid;

PK 컬럼으로 할 멤버필드에는 @Id 어노테이션을 붙인다.

 

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "guest_guest_no_seq")

@SequenceGenerator(name = "guest_guest_no_seq", sequenceName = "guest_guest_no_seq", initialValue = 1, allocationSize = 1)

@GeneratedValue() 시퀀스 같이 데이터를 자동으로 생성해준다. 

@SequenceGenerator(name="", sequenceName="", ...) 

sequenceName은 실제로 생성되는 물리적인 seq의 이름이고 name은 개발자가 sequence에 붙여준 이름으로 

GeneratedValue에 generator 이름은 @Generator 의 name을 입력한다. 

 

 

@Entity(name="user")

@Table(name="userinfo")

@Data

@AllArgsConstructor

@NoArgsConstructor

@Builder

public class User {

@Id

private String userId;

private String password;

private String name;

private String email;

}

 

이렇게 설정하고 실행시키면 userinfo 테이블이 생성된다. 

#테이블 자동 생성 옵션

spring.jpa.hibernate.ddl-auto=create

userId 카멜케이스로 하면 JPA는 테이블에 스네이크케이스로 바꿔준다.

 

private String userid;

private String password;

private String name;

private String email;

userid로 하면 테이블에 

userid 로 컬럼명이 설정된다. 

 

컬럼명을 명시해주고 싶을 땐 @Column(name="") 어노테이션을 사용

@Column(name="useridTest")

@Id

private String userid;

 

 

 

++

private String user_id;

만약 user_id라고 스네이크 케이스로 객체의 멤버변수명을 설정하면 

나중에 JPA에서 쿼리를 날릴때 문제가 생길 수 있으므로 사용을 지양한다.

 

 

 

@Column 어노테이션을 컬럼에 length, nuallable, constraints 등을 설정할 수 있다. 

@Column(length = 10, nullable = false)

 

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "guest_guest_no_seq")

@SequenceGenerator(name = "guest_guest_no_seq", sequenceName = "guest_guest_no_seq", initialValue = 1, allocationSize = 1)

@Id

private Long guestNo;//wrapper객체로 쓰는게 좋고 Integer보단 long

 

JPA를 사용할 땐 가급적 기본형보단 WrapperClass를 사용해주는게 좋은데 

자릿수가 짧은 Integer보단 Long을 사용하는 것이 좋다.

 

@ColumnDefault("sysdate")

private Date guestDate;

컬럼에 default 값을 설정해줄때는 

@ColumnDefault 어노테이션을 사용한다. 

 

또는 Column에 columnDefinition에 ddl에 작성하는 columnDefinition부분을 작성하면 된다. 

DATE DEFAULT SYSDATE

@Column(columnDefinition = "date default sysdate")

private Date guestDate;

 

 

repository 인터페이스 생성 

 

Jpa를 사용하기 위해  JpaRepository<entity,idtype>  상속extends 

JpaRepository는 CrudRepository를 상속하고 

CrudRepository는 

<S extends T> S save(S entity);

<S extends T> Iterable<S> saveAll(Iterable<S> entities);

Optional<T> findById(ID id);

boolean existsById(ID id);

...

등 비즈니스에 필요한 다양한 메소드들이 있다. 

 

Repository test하기 

 

 

repository에서 new- JUnit Test Case 생성

TestCase를 생성하면 Repository에서 상속한 인터페이스와 그 상위 인터페이스들의 메소드들을 테스트 할 수 있다. 

테스트할 클래스에 @SpringBootTest 어노테이션을 붙여주거나 

SpringJpaApplicationTests를 상속받아 SpringJpaApplicationTests의 @SpringBootTest도 상속받아 쓴다. 

@DisplayName("회원아이디로 찾기")

@Test

@Disabled

void testFindById() {

Optional<User> optionalUser = userRepository.findById("guard1");

// optional객체는 null일 수 없다.

if (optionalUser.isPresent()) {

User findUser1 = optionalUser.get();

System.out.println(findUser1);

}

}

 

 

 

JPA에서 기본 쿼리가 아닌 쿼리가 필요할 때에도 SQL문을 작성할 필요가 없다.(물론 직접 작성해줄 수도 있다.)

 

JPA는 method Interceptor로 메소드의 호출시 method를 가로채 메소드의 이름으로 필요한 쿼리를 작성해 구현해준다. 

그래서 우리가 어떤 쿼리가 필요하면 그에 맞게 이름을 지어줘야한다. 

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation

 

Spring Data JPA - Reference Documentation

Example 121. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

메소드 이름 짓는 방법은 위 문서에 나와있다. 

 

List<User> findByName(String name);

List<User> findByNameAndEmail(String name,String email);

List<User> findFirst2ByName(String name);

List<User> findTop2ByName(String name);

List<User> findByNameContains(String name);

List<User> findByNameStartingWith(String name);

List<User> findByNameLike(String name);

System.out.println(">>>findByNameLike :"+userRepository.findByNameLike("%경호%").size());

리턴 타입으로는 

void, 기본형, Wrapper, T(Object), Optional<T>, List<T>, Stream<T>, Iterator<T>, Collection<T>, Page<T>, Slice<T> ...

메소드의 이름은

find, get, search, read, stream, query, count... 으로 시작하고 

find(_찾을객체_)By_조건 형식으로 한다.

 

@Query 어노테이션 : 쿼리를 직접 작성할 때 

@Query(value="select * from userinfo where name=?1",nativeQuery = true)

List<User> findByNameSQL(String name);

nativeQuery는 JPQL이 아닌 SQL문을 그대로 작성할 때 사용한다.

 

select * from userinfo where name=?1에서 

?1은 매개변수 순서를 나타낸다. 

?1 자리에 첫번째 매개변수인 String name이 들어간다는 뜻이다. 

 

@Test

@DisplayName("방명록저장")

void save() {

Guest guest = Guest.builder().guestName("name").guestEmail("email").guestHomepage("home").guestContent("content").guestTitle("title").build();

System.out.println(guestRepository.save(guest));

System.out.println(guest);

}

guest와 save한 후 반환되는 guest는 같은 객체이다 

guest에 save해서 pk가 생성되었을때 guest에도 pk가 set된다. 

*@ColumnDefault("sysdate")로 디폴트 값을 설정해주었는데 guestDate=null 값이다..

 

hibernate에서 제공하는 @CreationTimestamp 어노테이션을 사용하면 된다. 

@Column(columnDefinition = "date default sysdate")

@CreationTimestamp// insert시 자동으로 값을 채워줌

private Date guestDate;

 

@Test

@DisplayName("방명록수정")

void update() {

Guest guest = guestRepository.findById(1L).get();

System.out.println("Guest 1L : "+guest);

guest.setGuestContent("내용");

guest.setGuestName("이름");

guestRepository.save(guest);

System.out.println("Guest 1L update: "+guest);

 

}

guest의 pk 타입은 Long 이기 때문에 1에 L을 붙여준다.

 

업데이트

guest update를 하는데 내용과 이름만 바꿨는데 쿼리는 모든것을 수정하고 있다. 

이는 성능에도 영향을 주기 때문에 수정이 필요한부분만 수정하는 쿼리를 만들도록 해준다.

@DynamicUpdate

public class Guest {

guest에 @DynamicUpdate 어노테이션을 추가한다.

 

한번에 여러 인스턴스를 업데이트하는 방법 

List<Guest> list =guestRepository.findByGuestNoBetween(1L, 5L);

for (int i = 0; i < list.size(); i++) {

list.get(i).setGuestName("nameChange");

}

guestRepository.saveAll(list);

 

saveAll()로 list를 모두 save 할 수 있다.

'Java > Spring Boot' 카테고리의 다른 글

JPA Object Relation Mapping  (0) 2023.10.11
JPA 계층형 게시판  (0) 2023.10.10
Spring CRUD with RestAPI  (0) 2023.09.20
Spring addViewControllers  (0) 2023.09.14
Thymeleaf in Spring  (0) 2023.09.14

+ Recent posts