묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
프록시 내부 호출 문제에 관한 질문 사항
보통 실무에서는controller ->service(interface) -> repository -> dao^|serviceImpl (service Interface 구현체)이렇게 많이 사용합니다. 제가 개발자로 실무를 하지 않아서 정확하지는 않지만@Configuratiain 을 이용한 클래스에서 구성을 잡고 포인트컷으로 지정된 패키지와 그 하위 *Impl 메서드에 모든 @Transaction 어노테이션이 적용되도록 설정을 했던 것 같습니다.그리고 serviceImpl에서 @Transactional 어노테이션을 사용하지 말라고 가이드가 내려 옵니다. 코딩은public class serviceImpl {public int createMember(MemberVO member) {deleteMember(member);insertMember(member);updateMember(member);} public int deleteMember(MemberVO member) {//비지니스 로직 수행String id = member.getId(); //null 체크 되어 있다고 가정repository.delete(id);}public int insertMember(MemberVO member) {//비지니스 로직 수행repository.insert(member);} public int updateMember(MemberVO member) {//비지니스 로직 수행repository.update(member);}} 그런데 한번도 아키텍처나 업무 공통 단에서 내부 호출에 대한 가이드가 없었습니다.그리고 실제로 내부 호출을 해도 Transaction 처리에 문제가 있지는 않았습니다.그렇다고 AspectJ 의 컴파일러를 이용하는 것 같지도 않고ObjectProvider를 사용하는 것 같지도 않는데 말입니다. 고급편에서도 궁금했지만 DB2편을 다 수강하고 나서 질문을 드립니다 아키텍처 쪽에서 내부 호출에 대한 문제를 모르진 않았을것 같은데통상적으로 어떻게 @Transactional 처리를 하기에 개발자들은 내부 호출 문제에 신경 쓰지 않을까요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
build.gradle에러
[질문 내용] ext["hibernate.version"] = "5.6.5.Final" 를 못 읽는것같습니다 뭐가 문제일까요 ??
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
querydsl
[질문 내용]안녕하세요 자바 17에 스프링 3이상으로 실습해보고있습니다.처음엔 의존관계 설정을implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" 이렇게 해줬는데 clean만 빌드가 되며 compileJava가 빌드가 안되고 그래들에서 의존관계에 빨간불이 뜨며 persistence를 찾을 수 없다는 에러 메세지가 나왔습니다찾아보던 도중 persistence버전을 3.0.1로 높이면 해결이 된다라는 글을 보고 버전을 올려줬습니다. 그 후 빌드를 해줬더니 jakarta로 import해주었던게 다 javax로 바뀌어있더라고요 그래서 일일히 들어가 다시 jakarta로 바꿔주니까 clean과 compileJava 둘 다 정상적으로 빌드되었습니다.하지만 그래들은 저렇게 아직 빨간불이 뜹니다 이대로 진행해도 되는걸까요 ? 왜 persistance 버전을 높이면 javax로 돌아가는건가요 ?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
dto 위치
만약 규모가 작은 프로젝트인 경우 현업에서 controller, service, vo 이런식으로 구조를 나누고 그 안에 비지니스 로직기준해서 폴더를 나누어 주는 경우도 있는데, 그 경우에는 말씀하셨던 비지니스따라 class파일을 만드는것과 크게 구조적으로 차이가 클까요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
@Transactional AOP 구현 질문
안녕하세요 영한님,@Transactional을 썻을때 스프링에서 구현해주는 AOP Proxy의 rollback시 동작순서에 궁금한점이 있어 질문드립니다. @Transactional 애노테이션이 붙은 method에서 예외가 발생해서 proxy구현체에서 롤백할시에 transaction 롤백 요청후 catch한 exception을 다시 던져주나요? 물론 AOP 구현체는 아래보다 복잡하겠지만, 아래와 비슷하게 동작하는지 궁금합니다.public Object implementTransactionalAOP(ProceedingJoinPoint pjp){ TransactionStatus tx = txManager.getTransaction(new DefaultTransactionAttribute()); try { Object ret = pjp.proceed(); txManager.commit(tx); return ret; }catch (RuntimeException e){ txManager.rollback(tx); throw new RuntimeException("",e); } }제가 괜히 코드를 집어넣어서 헷갈리게 해드리는것 같지만, 질문의 요점은 예외가 터졌을때 rollback만 요청해주는지 아니면 예외를 잡아서 같은예외를 다시 던져주는지가 궁금합니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
application.properties datasource질문
Test 부분에서 application.properties에 spring.profiles.active=test #spring.datasource.url=jdbc:h2:tcp://localhost/~/testcase #spring.datasource.username=sa #jdbcTemplate sql log logging.level.org.springframework.jdbc=debugurl과 username을 추가했었는데 h2 서버를 띄우지도 않았는데 작동되는 이유가 무엇인가요? (저 주석은 마지막강의 임베디드 메모리 강의듣느라 주석처리했습니다.) 이미 서버를 한번 띄었었기 때문에 작동이 되는것인지 궁금합니다
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
KeyHolder 질문
@Override public Item save(Item item) { String sql = "insert into item (item_name, price, quantity) " + "values(:itemName, :price, :quantity)"; SqlParameterSource param = new BeanPropertySqlParameterSource(item); KeyHolder keyHolder = new GeneratedKeyHolder(); template.update(sql, param, keyHolder); long key = keyHolder.getKey().longValue(); item.setId(key); return item; } KeyHolder같은경우 id를 내부에서 직접 구성해줘야하기 때문에 쓰는거라고 알고있는데 서버를 열어서 추가를 해줄때마다 숫자가 증가되는걸 볼수있었습니다. 숫자가 증가되는건 코드에서 자체적으로 해주는건가요?항상 답변감사드립니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
src/test/resources 에 application.properties
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]이전 수업까지datasource를 저희가 주입하는게 아닌 properties 파일로 자동으로 주입받을 때 src/test/resources 를 만든적이 없는걸로 기억합니다. 그런데도 에러 없이 잘 돌아갔었는데 src/test/resources 를 만들어서 분리하는 순간 src/test/resources에 있는 properties 파일은 src/test 를 위한 설정 파일이 되는건가요? 만약 src/test/resources를 만들지 않았다면 src/main에 있는 설정 정보를 그대로 src/test에서도 끌어다 쓰는건가요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
@Repository 사용 차이점
안녕하세요강의 중에 MyBatisItemRepository는 @Repository가 있고Jdbc관련 Repository에는 애너테이션이 안 붙여져 있는데 그 이유가 무엇인가요?
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
BeanPropertySqlParameter 사용 시 질문있습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]Item 클래스에 getId()도 있는데BeanPropertySqlParameterSouce(item)을 사용하면id값도 만들어지나요??
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
@Transactional 질문이 있습니다.
강의 중 트랜잭션 관련 부분을 보다 @Transactional과 직접 트랜잭션을 사용하는 예제를 떠올려 생각중인데 제가 생각한것이 맞는지 궁금하여 질문드립니다. @Transactional이 적용된 A클래스의 메서드에서@Transactional이 적용되지 않은 B클래스의 메서드를 호출하고B클래스 메서드의 내부는 직접 트랜잭션 매니져로 트랜잭션을 생성하고 롤백하는 로직이 포함되어 있는 상황이 있다고 가정한다면 트랜잭션 처리 순서는A클래스에서 트랜잭션이 시작되고 B클래스는 @Transactional이 없어서 트랜잭션AOP 프록시가 생성되지 않는것과는 상관없이 트랜잭션 매니져로 직접 생성한 트랜잭션으로 인해 A클래스의 트랜잭션에 합류하게 되어 B클래스의 롤백으로 인해 결과는 모두 롤백되는게 맞는걸까요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
@Servcie, @Repository annotation 질문입니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 아니오3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]강의에서 @SpringBootApplication(scanBasePackages = "hello.itemservice.web") 로 controller 부분 package 만 componentscan하고 나머지 설정부분은 @Import 를 통해서 @configuration 파일을 componentscan하는걸로 이해하고있는데 service, repository의 package에 bean을 config 파일에서 직접 등록하고 의존주입하고있는 상태에서 @Service , @Repository annotation 생략해도 되는데 사용한 이유가 서비스계층, repository계층을 명시 해주기 위해서 사용한 것 인지 궁금해서 질문 남깁니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
트랜잭션 readonly 거는 이유
@Slf4j static class BasicService { @Transactional public void tx1() { } @Transactional(readOnly = true) public void tx2() { } }만약에 이렇게 코드를 만드는데 tx2에서 트랜잭션을 readonly를 언제 보통 거는걸까요?tx2에 메소드에서 어차피 @Transactional(readOnly) 를 거나 안거나 성능은 별차이가 없는걸까요?두번째는 어차피 수정 삭제도아니고 조회인데 굳이 트랜잭션을@Transactional(readOnly = true) 거는 이유는 어떤경우가 있나요? 조회를 할때도 트랜잭션이 필요할때가 있어요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
트랜잭션 프록시 컨테이너 호출 관계
이 그림에서요 basicService 프록시가 컨테이너에 빈으로 등록되어서 테스트 코드 클래스로 주입된다고하셨는데, 그러면 뒤에 실제 객체는 컨테이너에 빈으로 등록이 실제로 안되어있는건가요?아니면 되어있는건가요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
트랜잭션 서비스 계층에서의 문제
트랜잭션을 리포지토리 말고 서비스 계층에 달면 문제가 생기네요ㅠㅠorg.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call 서비스 계층서 클래스레벨에 트랜잭션 달고 실행시 이렇게 ..나오는데 레포지토리에달면 잘 동작하는데.. 서비스 계층에 달면 왜그런걸까요..
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
외래키 중복 관련 질문
import com.example.banking.domain.user.User import com.example.banking.support.BaseEntity import jakarta.persistence.Entity import jakarta.persistence.FetchType import jakarta.persistence.JoinColumn import jakarta.persistence.ManyToOne @Entity class Account( var balance: Double, @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") val user: User, id: Long = 0 ) : BaseEntity(id) { fun addAccount(user: User) { user.accounts.add(this) } fun addBalance(amount: Double) { balance += amount } fun subtractBalance(amount: Double) { balance -= amount } }import com.example.banking.domain.account.Account import com.example.banking.support.BaseEntity import jakarta.persistence.* @Entity class Transaction( val amount: Double, @Enumerated(EnumType.STRING) val type: TransactionType, @ManyToOne(fetch = FetchType.LAZY) @JoinColumn val sender: Account, @ManyToOne(fetch = FetchType.LAZY) @JoinColumn val recipient: Account?, id: Long = 0L ) : BaseEntity(id) { constructor(amount: Double, type: TransactionType, sender: Account) : this(amount, type, sender, null) } import com.example.banking.domain.account.Account import com.example.banking.domain.user.User import com.example.banking.domain.user.UserInfo import com.example.banking.repository.account.AccountRepository import com.example.banking.repository.transaction.TransactionRepository import com.example.banking.repository.user.UserRepository import jakarta.persistence.EntityManager import jakarta.transaction.Transactional import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.annotation.Rollback @SpringBootTest @Transactional @Rollback(value = false) class TransactionTest( @Autowired private val em: EntityManager, @Autowired private val transactionRepository: TransactionRepository, @Autowired private val userRepository: UserRepository, @Autowired private val accountRepository: AccountRepository ) { @Test fun testTransaction() { val user1 = User(UserInfo("b", "Seoul", "123", "123")) val user2 = User(UserInfo("b2", "Seoul", "123", "123")) userRepository.save(user1) userRepository.save(user2) em.flush() em.clear() val account1 = Account(100.0, user1) val account2 = Account(100.0, user2) account1.addAccount(user1) account2.addAccount(user2) accountRepository.save(account1) accountRepository.save(account2) em.flush() em.clear() val sender = accountRepository.findById(account1.id).get() val recipient = accountRepository.findById(account2.id).get() val transaction = Transaction(50.0, TransactionType.TRANSFER, sender, recipient) transactionRepository.save(transaction) em.flush() em.clear() val transaction2 = Transaction(50.0, TransactionType.DEPOSIT, sender) transactionRepository.save(transaction2) // assertThat(sender.balance).isEqualTo(50.0) // assertThat(recipient.balance).isEqualTo(150.0) } } 위와같이 Transaction 엔티티와 Account 엔티티가 ManyToOne 으로 매핑되었을때, 테스트코드를 위와같이 작성시,transactionRepository.save(transaction2) 이 라인에서 Duplicate entry '97' for key 'transaction.UK_96vb4d846be64bta5qbxiicb1' 에러가 발생합니다.제가 알기론 외래키의 경우 중복된 값을 가지는것이 가능한것으로 알고 있는데, 같은 account id로 새로운 Transaction 을 생성할 시에 키가 중복이라는 에러가 발생하는데 왜 그런지 알고싶습니다. 코틀린으로 코드 작성한 점 양해부탁드립니다..
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
의존성 주입
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]강의를 듣다가 순간 애매해서 질문드립니다. V2config에서 해당 코드를@Bean public ItemService itemService() { return new ItemServiceV2(itemRepositoryV2, itemQueryRepositoryV2()); } @Bean public ItemQueryRepositoryV2 itemQueryRepositoryV2(){ return new ItemQueryRepositoryV2(em); }@Bean public ItemService itemService() { return new ItemServiceV2(itemRepositoryV2, new ItemQueryRepositoryV2(em)); } /** @Bean public ItemQueryRepositoryV2 itemQueryRepositoryV2(){ return new ItemQueryRepositoryV2(em); } **/ 처럼 ItemQueryRepositoryV2부분은 주석처리 해서 @Bean으로 등록을 하지 않으면 작동이 안돼야 할까요?? 변경하고 작동해봤는데 문제가 없어서 질문드립니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
simplejdbcinsert
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]simplejdbcinsert를 여러 테이블에 적용해야 한다면 적용할 테이블 개수에 맞춰서 객체를 생성해줘야 할까요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
내부 클래스에 @Slf4j를 적용하는 이유
강의에서 내부 클래스에도 @Slf4j를 적용하는 것을 확인할 수 있는데 그 이유가 궁금합니다!@Slf4j @SpringBootTest public class TxBasicTest { @Slf4j static class BasicService { } }
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
@Transactional 적용 (Spring Data JPA, JPA 상황에 따른..)
섹션 8의 <실용적인 구조> 강의에서 질문드립니다.JPA의 모든 데이터 변경은 트랜젝션 안에서 일어나기 때문에 JPA를 사용할 때는 리포지토리 계층에 @Transactional을 붙여야한다고 배웠습니다.그런데 Spring Data JPA는 @Transactional을 붙이지 않아도 @Transactional 처리를 자동으로 한다는 것 같은데 맞는 얘긴가요?원래 트랜젝션 적용은 서비스 계층에서 이뤄저야한다고 배웠습니다. 그래서 서비스 계층에서 @Transactional을 붙여왔고요. 그런데 해당 강의의 8분 지점에서 ItemServiceV2의 경우 Spring Data JPA에 의존하고 있기 때문에 리포지토리 계층에서는 @Transactional을 적용하지 않았고 서비스 계층인 ItemServiceV2에서 @Transactional을 적용한 것 같은데 맞을까요?