@Setter
public class MyRepository {
private HashMap<Long, String> dataTable; // DB 테이블을 의미
public String find(Long id) {
return dataTable.getOrDefault(id, "");
}
public Long save(String data) {
var newId = Long.valueOf(dataTable.size());
this.dataTable.put(newId, data);
return newId;
}
}
public class MyRepositoryRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
// 주입할 빈에 대해 프로그래밍 하는 부분!!
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(MyRepository.class);
beanDefinition.getPropertyValues().add("dataTable", Map.of(1L, "data"));
// 여기까지!
registry.registerBeanDefinition("myRepository", beanDefinition);
}
}
@Import(MyRepositoryRegistrar.class) // 빈 주입!
@SpringBootTest
public class MyRepositoryTest {
@Autowired
MyRepository myRepository;
@Test
void myRepositoryTest() {
// given
var newData = "NEW DATA";
var savedId = myRepository.save(newData);
// when
var newDataList = myRepository.find(savedId);
// then
System.out.println(newDataList);
}
}
기존 Repository vs 새로운 JpaRepository
Repository 를 JpaRepository 로 간단하게 바꾸기!
// 변경 전
@Repository
public class UserRepository {
@PersistenceContext
EntityManager entityManager;
public User insertUser(User user) {
entityManager.persist(user);
return user;
}
public User selectUser(Long id) {
return entityManager.find(User.class, id);
}
}
// 변경 후
public interface UserRepository extends JpaRepository<User, Long> {
}
- JpaRepository 에서 사용할 메소드 제한하기
- JpaRepository 는 기본적으로 모든 기능을 제공하기 때문에 리스크가 있을 수 있다.
- 따라서, 아래와 같은 방법으로 원하는 기능 메소드만 구현하도록 제한할 수 있다.
- findAll, saveAll, deleteAll등 쓰지 않는것들도 있을탠데 자동으로 나온다.
@RepositoryDefinition(domainClass = Comment.class, idClass = Long.class)
public interface CommentRepository {
Comment save(Comment comment);
List<Comment> findAll();
}
@NoRepositoryBean
public interface MyRepository<T, ID extends Serializable> extends Repository<T, ID> {
<E extends T> E save(E entity);
List<T> findAll();
}
delete() 메소드의 내부 기능 확인하기
- delete 호출시 영속성 상태인지 확인한다.
- 영속성 컨텍스트에 없다면(
!em.contains(entity)
) 엔티티를 조회해서 영속성 상태로 바꾼다.- 어차피 삭제할껀데 굳이?!?!
- Cascade, orphanRemoval 에 의한 자식도 삭제가 누락되지 않도록!!!
- JpaRepository 의 delete() 는 해당 엔티티를 바로 삭제하지 않는다.
- remove() 메소드를 통해 remove 상태로 바꾼다.
public interface MyRepository {
public void delete(User user);
public List<String> findNameAll();
}
@Repository
@Transactional
public class MyRepositoryImpl implements MyRepository {
@Autowired
EntityManager entityManager;
//1. delete 쿼리가 바로 날아가도록 기능을 개선해보자
@Override
public void delete(User user) {
entityManager.remove(user);
}
//2. findAll 할때 이름만 가져오도록 기능을 추가해보자
@Override
public List<String> findNameAll() {
return entityManager.createQuery("SELECT u.username FROM User AS u", String.class).getResultList();
}
}