@Id olarak işaretli alana göre arama yapar.
Problem1 - findById() metodunun Döngü İçinde Kullanılması
Eğer birden fazla nesne almak istiyorsak findAllById() kullanılır
Örnek
Şöyle yaparız
@Service public class UserService { @Autowired private UserRepository userRepository; public List<User> getUsersByIds(List<Long> ids) { return userRepository.findAllById(ids); } }
Üretilen SQL şöyle
SELECT * FROM User user WHERE user.id IN :ids
Problem 2
Açıklaması şöyle. Yani findById() lazy değildir. OneToMany, ManyToOne gibi ilişkilerde diğer taraftaki nesneleri de getirir.
Another issue with findById is that it can lead to the creation of many unnecessary objects. Each time you call findById, Spring Data JPA creates a new entity object, even if the entity is already in the persistence context. This can lead to a significant increase in memory usage and garbage collection overhead.
findById() yerine getReferenceById() tercih edilmeli
getReferenceById() metodunun kodu şöyle. Yeni bir proxy dönüyor
public T getReferenceById(ID id) { Assert.notNull(id, "The given id must not be null!"); return this.em.getReference(this.getDomainClass(), id); }
getReferenceById metodunun hikayesi şöyle. Yani önce getOne() -> daha sonra getById() -> daha sonra getReferenceById() haline gelmiş.
Initially, Spring Data JPA offered a getOne method that we should call in order to get an entity Proxy. But we can all agree that getOne is not very intuitive.So, in the 2.5 version, the getOne method got deprecated in favor of the getById method alternative, that’s just as unintuitive as its previous version.Neither getOne nor getById is self-explanatory. Without reading the underlying Spring source code or the underlying Javadoc, would you know that these are the Spring Data JPA methods to call when you need to get an entity Proxy?Therefore, in the 2.7 version, the getById method was also deprecated, and now we have the getReferenceById method instead,...
Örnek - OneToMany İlişki
Elimizde şöyle bir kod olsun. Department nesnesi Employee nesnesine OneToMany ile bağlı. Employee nesnesi de Department nesnesine ManyToOne ile bağlı
@Entity @Table(name = "departments") public class Department { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "department", fetch = FetchType.LAZY) private List<Employee> employees = new ArrayList<>(); // getters and setters } @Entity @Table(name = "employees") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "department_id") private Department department; // getters and setters }
Şöyle kullanalım
@Service public class DepartmentService { @Autowired private DepartmentRepository departmentRepository; public Department getDepartmentById(Long id) { return departmentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Department not found with id " + id)); } }
Üretilen SQL şöyle
SELECT * FROM departments WHERE id = ? SELECT * FROM employees WHERE department_id = ?
Düzeltmek için şöyle yaparız. Burada getOne() kullanılıyor ancak getReferenceById() de aynı şey zaten
@Service public class DepartmentService { @Autowired private DepartmentRepository departmentRepository; public Department getDepartmentReferenceById(Long id) { return departmentRepository.getOne(id); } }
Üretilen SQL şöyle
SELECT department FROM Department department WHERE department.id = ?
Açıklaması şöyle
Note that the actual SQL query to fetch the related Employee objects will only be executed when we access the employees property of the Department object, or call a method on one of its related employees that requires database access.
Örnek - ManyToOne İlişki
Elimizde şöyle bir kod olsun
@Entity@Table(name = "post")public class Post {@Idprivate Long id;private String title;@NaturalIdprivate String slug;}@Entity@Table(name = "post_comment")public class PostComment {@Id@GeneratedValueprivate Long id;private String review;@ManyToOne(fetch = FetchType.LAZY)private Post post;}
Şöyle kullanalım. Aslında yeni bir PostComment nesnesi ekliyoruz ve bunun için ilişkili olduğu Post nesnesine ihtiyaç var.
@Transactional(readOnly = true)public class PostServiceImpl implements PostService {@Autowiredprivate PostRepository postRepository;@Autowiredprivate PostCommentRepository postCommentRepository;@Transactionalpublic PostComment addNewPostComment(String review, Long postId) {PostComment comment = new PostComment().setReview(review).setPost(postRepository.findById(postId).orElseThrow(()-> new EntityNotFoundException(String.format("Post with id [%d] was not found!", postId))));postCommentRepository.save(comment);return comment;}}
Üretilen SQL şöyle
SELECT post0_.id AS id1_0_0_, post0_.slug AS slug2_0_0_, post0_.title AS title3_0_0_ FROM post post0_ WHERE post0_.id = 1 SELECT nextval ('hibernate_sequence') INSERT INTO post_comment ( post_id, review, id ) VALUES ( 1, 'Best book on JPA and Hibernate!', 1 )
Kodu şöyle yapalım. Burada artık getReferenceById() kullanılıyor
@Transactional public PostComment addNewPostComment(String review, Long postId) { PostComment comment = new PostComment() .setReview(review) .setPost(postRepository.getReferenceById(postId)); postCommentRepository.save(comment); return comment; }
Üretilen SQL şöyle
SELECT nextval ('hibernate_sequence') INSERT INTO post_comment ( post_id, review, id ) VALUES ( 1, 'Best book on JPA and Hibernate!', 1 )
Hiç yorum yok:
Yorum Gönder