gradle 설정
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.13'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '1.8'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// queryDSL 설정
implementation "com.querydsl:querydsl-jpa"
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-collections"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드
}
tasks.named('test') {
useJUnitPlatform()
}
// Querydsl 설정부
def generated = 'src/main/generated'
// querydsl QClass 파일 생성 위치를 지정`
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(generated))
}
// java source set 에 querydsl QClass 위치 추가
sourceSets {
main.java.srcDirs += [ generated ]
}
// gradle clean 시에 QClass 디렉토리 삭제
clean {
delete file(generated)
}
properties 설정
#mysql
spring.datasource.url=jdbc:mysql://localhost:포트/DB이름
spring.datasource.username=아이디
spring.datasource.password=비밀번호
# hibernate
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=validate
#spring.jpa.properties.hibernate.format_sql=true
#spring.jpa.properties.hibernate.use_Sql_comments=true
logging.level.org.hibernate.type.descriptor.sql=trace
Config 설정
@Configuration
@EnableJpaRepositories(basePackages = "com.example.querydsl.repository")
public class QuerydslConfig {
@PersistenceContext
private EntityManager entityManager;
public JPAQueryFactory jpaQueryFactory(){
return new JPAQueryFactory(entityManager);
}
}
Entity 설정 예시로 Person 만듬
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
}
repository
public interface PersonRepository extends JpaRepository<Person, Long>, QuerydslPredicateExecutor<Person> {
}
service
public interface PersonService {
Person createPerson(Person person);
Optional<Person> getPersonById(Long id);
List<Person> getAllPersons();
Person updatePerson(Person updatedPerson);
void deletePersonById(Long id);
void deleteAllPersons();
}
serviceImpl
@Service
public class PersonServiceImpl implements PersonService{
private final PersonRepository personRepository;
private final JPAQueryFactory queryFactory;
public PersonServiceImpl(PersonRepository personRepository, EntityManager entityManager) {
this.personRepository = personRepository;
this.queryFactory = new JPAQueryFactory(entityManager);
}
@Override
public Person createPerson(Person person) {
return personRepository.save(person);
}
@Override
public Optional<Person> getPersonById(Long id) {
QPerson person = QPerson.person;
return Optional.ofNullable(queryFactory.selectFrom(person)
.where(person.id.eq(id))
.fetchOne());
}
@Override
public List<Person> getAllPersons() {
// return personRepository.findAll();
QPerson person = QPerson.person;
return queryFactory.selectFrom(person).fetch();
}
@Override
public Person updatePerson(Person updatedPerson) {
return personRepository.save(updatedPerson);
}
@Override
public void deletePersonById(Long id) {
personRepository.deleteById(id);
}
@Override
public void deleteAllPersons() {
personRepository.deleteAll();
}
}
이후 실행하면 Person의 Qclass가 generated에 자동 생성된다.
junit test도 해봤다
@SpringBootTest
@Transactional
public class PersonServiceTest {
@Autowired
private PersonService personService;
@Autowired
private PersonRepository personRepository;
@Autowired
private DataInitializer dataInitializer;
@Autowired
private EntityManager entityManager;
private JPAQueryFactory queryFactory;
@BeforeEach
public void initializeData(){
dataInitializer.initializeDummyData();
}
@BeforeEach
public void createJPAConnect(){
queryFactory = new JPAQueryFactory(entityManager);
}
@AfterEach
public void clearData(){
personService.deleteAllPersons();
}
@Test
@DisplayName("Person 생성 메서드")
public void testCreatePerson(){
//given
Person person = new Person(4L,"Tony",30);
//when
Person createdPerson = personService.createPerson(person);
//then
Optional<Person> retrievedPerson = personRepository.findById(createdPerson.getId());
assertTrue(retrievedPerson.isPresent());
assertEquals("Tony", retrievedPerson.get().getName());
assertEquals(30,retrievedPerson.get().getAge());
System.out.println(retrievedPerson);
}
@Test
@DisplayName("Person 모두 조회")
public void testGetPersonAll(){
//given
List<Person> allPerson = personRepository.findAll();
//when
QPerson qPerson = QPerson.person;
List<Person> findAllPerson = queryFactory.selectFrom(qPerson).fetch();
//then
assertThat(findAllPerson).hasSize(allPerson.size());
assertThat(findAllPerson).containsExactlyInAnyOrderElementsOf(allPerson);
System.out.println(findAllPerson);
}
@Test
@DisplayName("Person Id로 삭제")
public void testDeletePersonById(){
//given
Long id = 1L;
Person person = new Person(id, "John", 25);
personRepository.save(person);
//when
QPerson qPerson = QPerson.person;
long deletedCount = queryFactory.delete(qPerson).where(qPerson.id.eq(id)).execute();
//then
assertEquals(1,deletedCount);
assertFalse(personRepository.existsById(id));
}
}
잘 된다.
@Component
public class DataInitializer {
private final PersonServiceImpl personService;
public DataInitializer(PersonServiceImpl personService) {
this.personService = personService;
}
@PostConstruct
public void initializeDummyData(){
List<Person> dummyPersons = generateDummyPersons();
for (Person person : dummyPersons) {
personService.createPerson(person);
}
}
public void clearDummyData(){
personService.deleteAllPersons();
}
private List<Person> generateDummyPersons() {
Person person1 = new Person(1L,"John", 25);
Person person2 = new Person(2L,"Jane", 30);
Person person3 = new Person(3L,"Mike", 35);
return Arrays.asList(person1, person2, person3);
}
}
p.s 2 /
테스트용 더미데이터를 만드는 기능이다.
test에 BeforeEach로 테스트 실행 전에 initializeDummyDate()로
테스트용 더미데이터를 만들고,
AfterEach()로 테스트용 더미데이터를 초기화 시켜준다.
아마 테스트안에 안 써서 새로히 더미데이터 추가,수정은 안되는 것으로 안다.
그래서 사실 테스트 안에 위의 DataInitializer 클래스를 넣는게 맞다..
설명 안해두면 이글을 본 누군가가 화낼거 같아서 다시 썼다..
'Spring > 공부' 카테고리의 다른 글
유효성 검사 예제 with jpa (0) | 2023.07.14 |
---|---|
Spring 유효성 검사 어노테이션 목록 (0) | 2023.07.11 |
Jpa 맛보기 - 1 (0) | 2023.07.05 |
메시지 국제화(언어 선택) (0) | 2023.06.15 |
서블릿 -> jsp (1) | 2023.04.14 |