Programing/Java & Spring

(Java&Spring) JPQL 활용하기[포토폴리오 싸이트 제작하기 2탄 - 세무민의 코딩일기]

세기루민 2022. 1. 4. 23:00
728x90

이번 포스팅에서는 JPA를 활용하는 내용에 대해서 알아보겠습니다. 

우선 최근에 개인적인 사정으로 코딩 공부를 못했는데 오랜만에 주말에 JPA에 대해서 공부를 조금 해봤습니다. 

 


JPA를 이용한 포토폴리오 싸이트 제작하는 코드와 자료들은 GITHUB에 업로드 하면서 진행하겠습니다. 

👇👇👇👇👇👇👇👇👇 현재까지 진행한 내용들은 아래의 주소에서 확인 가능합니다. 👇👇👇👇👇👇👇👇👇

 

GitHub - sg-moomin/Spring_Jpa_miniProjects

Contribute to sg-moomin/Spring_Jpa_miniProjects development by creating an account on GitHub.

github.com


우선 전에 진행했던 내용에서 추가하여 진행하였고 전에 했던 내용들은 아래의 포스팅에서 확인 가능합니다. 

 

(JAVA) JPA에 대해서 알아보자 [포토폴리오 싸이트 제작하기 1탄 - 세무민의 코딩일기]

이번 포스팅에서는 JPA에 대해서 알아보도록 합시다. 제가 예전에 JDBC에서 Mybatis까지 사용했었는데 현재는 JPA를 자주 사용한다고 해서 공부를 해봤습니다. 1. JPA? JPA란 말 그대로 (Java Persistence API)

sg-moomin.tistory.com

 

이번에 확인해 볼 페이지는 포스팅 페이지입니다. 

포토폴리오 화면에서 뜬금없이 왜 포스팅 페이지냐고 궁금해 하실 수 있는데

해당 페이지를 통해 JPQL을 다룰 것이기 때문입니다.

우선 HTML을 제외한 자바 로직만 다뤄보도록 하겠습니다.  


Controller
@Controller
@RestController	
@RequiredArgsConstructor
public class mainController {

	private blogPostRepository blogPostRepository;

	@Autowired
	public blogPostEntityService blogPostEntitySvc;
		
	@RequestMapping(value="/index", method=RequestMethod.GET)
	public ModelAndView main(ModelAndView M) {
	
    		List<noticeboardEntity> result = profileEntitySvc.mainInit();
		M.addObject("main", result);
		M.setViewName("index");
		return M;
	}
	
	@ResponseBody
	@RequestMapping(value="/blogPost", method=RequestMethod.GET)
	public ModelAndView blogPost(ModelAndView M, String findPostId) {
			
		List<blogPostEntity> result = blogPostEntitySvc.searchFindId(findPostId);
		List<blogPostEntity> titles = blogPostEntitySvc.findByPostMainTitle();

		M.addObject("myPost", result);
		M.setViewName("blogPost");
		
		
		return M;
	}
}

우선 blogPost view에서 컨트롤러로 findPostId와 모델을 넘겨준 뒤 해당 값들을 SearchFindId와 findByPostMainTitle

서비스로 넘겨서 값을 가져올 것입니다. 

Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
// table connect
@Entity(name="blogpost")
public class blogPostEntity {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private String postid;
	
	@Column(nullable = false, length = 500)
	private String postmaintitle;
	
	@Column(nullable = false, length = 100)
	private String postsntitle;

	@Column(nullable = false, length = 1000)
	private String postsn;
	
	@Column(nullable = false, length = 300)
	private String posturl;

	@Column(nullable = false, length = 300)
	private int postlvl;

	@Column(nullable = false, length = 300)
	private int postupperlvl;

	//	@Builder
	public blogPostEntity(String postmaintitle, String postsntitle, String postsn, String posturl) {
		this.postmaintitle = postmaintitle;
		this.postsntitle = postsntitle;
		this.postsn = postsn;
		this.posturl = posturl;
	}

}

 

 Entity는 옆의 그림처럼 DB의 blogPost 테이블의 컬럼과 동일하게 맞춰줍니다. 

 

 

Service / ServiceImpl
/***
* Service 로직 부분
*/

public interface blogPostEntityService {

	
	// 전체 조회 
	public List<blogPostEntity> init();
	// ID 조회
	public List<blogPostEntity> searchFindId(String findId);
	public List<blogPostEntity> findByPostMainTitle();
	
}


/***
* Service Impl 로직 부분 
*/

@Service
@RequiredArgsConstructor
public class blogPostEntityServiceImpl implements blogPostEntityService {
	
	final private blogPostRepository blogPostRepository;
	
	@Override
	public List<blogPostEntity> init() {
		List<blogPostEntity> result = this.selectFindAllData();
		return result;
	}

	@Override
	public List<blogPostEntity> searchFindId(String findId) {
	
		List<blogPostEntity> result = new ArrayList<blogPostEntity>();
		
		List<blogPostEntity> postList = this.selectFindAllData();
		for(blogPostEntity blogPost : postList) {
			if(blogPost.getPostid().equals(findId)) {
				blogPost.getPostsn().replace("\r\n", "<br>");
				System.out.println("blogPost ::::: " + blogPost.getPostsn());
				
				result.add(blogPost);
				break;
			}
		} 
		
		return result;
	}

	/**
	 * FindAll 데이터 조회
	 * */
	private List<blogPostEntity> selectFindAllData(){
		List<blogPostEntity> result = blogPostRepository.findAll();
		return result;
	}

	@Override
	public List<blogPostEntity> findByPostMainTitle() {		
		List<blogPostEntity> postList = new ArrayList<blogPostEntity>();
		postList = blogPostRepository.findByPostMainTitle("2021 티스토리 테스트");
		return postList;
	}
	
}

우선 service에서 SearchFindId와 findByPostMainTitle 2개를 중점으로 보면 된다. 

SearchFindId라는 매소드는 CRUDRepositroy의 기본 인터페이스로 제공해주는 FindAll을 이용하였고 

findByPostMainTitle의 경우는 Repository를 보면 알겠지만 JPQL을 사용한 로직이다. 

Repository
@Repository
public interface blogPostRepository extends JpaRepository<blogPostEntity, Integer> {

	@Query(value = "SELECT * FROM BlogPost where postmaintitle = :postMainTitle", nativeQuery = true)
	List<blogPostEntity> findByPostMainTitle(@Param("postMainTitle") String postMainTitle);
	
	
}

FindByPostMainTitle의 경우 JPQL을 사용한 내용이다. 

DB(blogPost)


우선 위의 그림의 결과는 SearchFindId를 이용하여 ID별로 값을 가져온 케이스이다. 

그래도 JPQL도 잘 돌아가는 지 확인하기 위해 Service 로직에서 하드코딩을 하여 테스트 해봤다. 

위의 그림처럼 동적으로 쿼리를 날렸을 때 내가 원하는 값을 가져올 수 있다. 

2. 현재 진행중인 화면

현재 나의 서비스라는 화면에서는 내가 현재 어떤 활동들을 하는지 알 수 있도록 기록하고 있다. 

현재 하고있는 블로그와 인스타 그리고 카카오뷰 정도로 구성했다. 

나의 포토폴리오 화면인데 이 화면을 어떻게 꾸밀지 사실 의문이다. 

그래서 현재는 그냥 단순하게 PDF만 붙여놓은 상태이다. 

해당 페이지를 좀 더 세부적으로 설계할 예정이다. 

마지막으로 Blog라는 페이지인데 이 페이지도 수정 예정이다. 

현재는 JPA 연동 테스트를 위해서 2020년도 read more 버튼만 활성화 시켜놓은 상태인데 해당 버튼 클릭하면 

아래의 화면을 볼 수 있다. 

 

3. 느낀점

JPA를 공부를 조금 했을 땐 CRUDRepository에서 제공해주는 인터페이스를 이용하여 서비스 로직에서 가공해야만 하는

줄 알았는데 공부를 하면서 왜 사람들이 JPA를 열광하는지 알 듯하다. 

 


참고 사이트 :  https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations

728x90