BAEL-6887: List vs Set in @OneToMany JPA (#15677)

This commit is contained in:
Eugene Kovko
2024-01-18 11:43:05 -08:00
committed by GitHub
parent 9801f1eb7d
commit 9aa37e2746
66 changed files with 3432 additions and 0 deletions
@@ -42,6 +42,26 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-62</artifactId>
<version>${hypersistence-utils.version}</version>
</dependency>
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>db-util</artifactId>
<version>${db.util.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<build>
@@ -58,6 +78,10 @@
<junit-jupiter.version>5.9.3</junit-jupiter.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<db.util.version>1.0.7</db.util.version>
<hypersistence-utils.version>3.7.0</hypersistence-utils.version>
<jackson.version>2.16.0</jackson.version>
<lombok.version>1.18.28</lombok.version>
</properties>
</project>
@@ -0,0 +1,14 @@
package com.baeldung.listvsset;
import java.lang.reflect.ParameterizedType;
import java.util.Arrays;
import java.util.List;
public abstract class ParametrizationAware<T> {
public List<Class<T>> getParametrizationClass() {
ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
return Arrays.stream(type.getActualTypeArguments())
.map(s -> ((Class<T>) s)).toList();
}
}
@@ -0,0 +1,63 @@
package com.baeldung.listvsset;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class Service<S> extends ParametrizationAware<S> {
private final JpaRepository<S, Long> repository;
public Service(JpaRepository<S, Long> repository) {
this.repository = repository;
}
public JpaRepository<S, Long> getRepository() {
return repository;
}
public int countNumberOfRequestsWithFunction(ToIntFunction<List<S>> function) {
return function.applyAsInt(repository.findAll());
}
public Optional<S> getUserById(Long id) {
return repository.findById(id);
}
public void deleteAll() {
repository.deleteAll();
}
public List<S> saveAll(Iterable<S> entities) {
return repository.saveAll(entities);
}
public List<S> findAll() {
return repository.findAll();
}
public Optional<S> getUserByIdWithPredicate(long id, Predicate<S> predicate) {
Optional<S> user = repository.findById(id);
user.ifPresent(predicate::test);
return user;
}
public int getUserByIdWithFunction(Long id, ToIntFunction<S> function) {
Optional<S> optionalUser = repository.findById(id);
if(optionalUser.isPresent()) {
return function.applyAsInt(optionalUser.get());
} else {
return 0;
}
}
public void save(S entity) {
repository.save(entity);
}
}
@@ -0,0 +1,8 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
}
@@ -0,0 +1,25 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import lombok.Data;
@Data
@Entity
public class Comment {
@Id
private Long id;
private String text;
@ManyToOne
private User author;
@JsonBackReference
@ManyToOne
private Post post;
}
@@ -0,0 +1,23 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import java.util.List;
import lombok.Data;
@Data
@Entity(name = "interest_group")
@Table(name = "interest_group")
public class Group {
@Id
private Long id;
private String name;
@ManyToMany(fetch = FetchType.EAGER)
private List<User> members;
}
@@ -0,0 +1,32 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import java.util.List;
import lombok.Data;
@Entity
@Data
public class Post {
@Id
private Long id;
@Lob
private String content;
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, mappedBy = "post", fetch = FetchType.EAGER)
private List<Comment> comments;
@JsonBackReference
@ManyToOne
private User author;
}
@@ -0,0 +1,7 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository<Post, Long> {
}
@@ -0,0 +1,28 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Lob;
import jakarta.persistence.OneToOne;
import lombok.Data;
@Entity
@Data
public class Profile {
@Id
private Long id;
@Lob
private String biography;
private String website;
private String profilePictureUrl;
@JsonBackReference
@OneToOne(mappedBy = "profile")
@JoinColumn(unique = true)
private User user;
}
@@ -0,0 +1,36 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.util.List;
import lombok.Data;
@Data
@Entity(name = "simple_user")
@Table(name = "simple_user")
public class User {
@Id
private Long id;
private String username;
private String email;
@JsonManagedReference
@OneToOne(cascade = CascadeType.ALL)
private Profile profile;
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, mappedBy = "author", fetch = FetchType.EAGER)
protected List<Post> posts;
@ManyToMany(mappedBy = "members", fetch = FetchType.EAGER)
private List<Group> groups;
}
@@ -0,0 +1,7 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
@@ -0,0 +1,20 @@
package com.baeldung.listvsset.eager.list.fulldomain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Service
public class UserService extends com.baeldung.listvsset.Service<User> {
public UserService(JpaRepository<User, Long> repository) {
super(repository);
}
@Override
public UserRepository getRepository() {
return ((UserRepository) super.getRepository());
}
}
@@ -0,0 +1,8 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
}
@@ -0,0 +1,23 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import java.util.List;
import lombok.Data;
@Data
@Entity(name = "interest_group")
@Table(name = "interest_group")
public class Group {
@Id
private Long id;
private String name;
@ManyToMany(fetch = FetchType.EAGER)
private List<User> members;
}
@@ -0,0 +1,7 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import org.springframework.data.jpa.repository.JpaRepository;
public interface GroupRepository extends JpaRepository<Group, Long> {
}
@@ -0,0 +1,29 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class GroupService {
private final GroupRepository groupRepository;
@Autowired
public GroupService(GroupRepository groupRepository) {
this.groupRepository = groupRepository;
}
public Optional<Group> findById(Long aLong) {
return groupRepository.findById(aLong);
}
public List<Group> findAll() {
return groupRepository.findAll();
}
public <S extends Group> S save(S entity) {
return groupRepository.save(entity);
}
}
@@ -0,0 +1,23 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import jakarta.persistence.ManyToOne;
import lombok.Data;
@Entity
@Data
public class Post {
@Id
private Long id;
@Lob
private String content;
@JsonBackReference
@ManyToOne
private User author;
}
@@ -0,0 +1,7 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository<Post, Long> {
}
@@ -0,0 +1,46 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.util.List;
import java.util.Objects;
import lombok.Data;
@Data
@Entity(name = "simple_user")
@Table(name = "simple_user")
public class User {
@Id
private Long id;
private String username;
private String email;
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, mappedBy = "author", fetch = FetchType.EAGER)
protected List<Post> posts;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
return Objects.equals(id, user.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
@@ -0,0 +1,7 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
@@ -0,0 +1,20 @@
package com.baeldung.listvsset.eager.list.moderatedomain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Service
public class UserService extends com.baeldung.listvsset.Service<User> {
public UserService(JpaRepository<User, Long> repository) {
super(repository);
}
@Override
public UserRepository getRepository() {
return ((UserRepository) super.getRepository());
}
}
@@ -0,0 +1,8 @@
package com.baeldung.listvsset.eager.list.simpledomain;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
}
@@ -0,0 +1,23 @@
package com.baeldung.listvsset.eager.list.simpledomain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import jakarta.persistence.ManyToOne;
import lombok.Data;
@Entity
@Data
public class Post {
@Id
private Long id;
@Lob
private String content;
@JsonBackReference
@ManyToOne
private User author;
}
@@ -0,0 +1,7 @@
package com.baeldung.listvsset.eager.list.simpledomain;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository<Post, Long> {
}
@@ -0,0 +1,26 @@
package com.baeldung.listvsset.eager.list.simpledomain;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.util.List;
import lombok.Data;
@Data
@Entity(name = "simple_user")
@Table(name = "simple_user")
public class User {
@Id
private Long id;
private String username;
private String email;
@JsonManagedReference
@OneToMany(cascade = CascadeType.ALL, mappedBy = "author", fetch = FetchType.EAGER)
protected List<Post> posts;
}
@@ -0,0 +1,9 @@
package com.baeldung.listvsset.eager.list.simpledomain;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.jpa.repository.JpaRepository;
@Lazy(value = false)
public interface UserRepository extends JpaRepository<User, Long> {
}
@@ -0,0 +1,20 @@
package com.baeldung.listvsset.eager.list.simpledomain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Service
public class UserService extends com.baeldung.listvsset.Service<User> {
public UserService(JpaRepository<User, Long> repository) {
super(repository);
}
@Override
public UserRepository getRepository() {
return ((UserRepository) super.getRepository());
}
}
@@ -0,0 +1,8 @@
package com.baeldung.listvsset.eager.set.fulldomain;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
}
@@ -0,0 +1,44 @@
package com.baeldung.listvsset.eager.set.fulldomain;
import com.fasterxml.jackson.annotation.JsonBackReference;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import java.util.Objects;
import lombok.Data;
@Data
@Entity
public class Comment {
@Id
private Long id;
private String text;
@ManyToOne
private User author;
@JsonBackReference
@ManyToOne
private Post post;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Comment comment = (Comment) o;
return Objects.equals(id, comment.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}
@@ -0,0 +1,43 @@
package com.baeldung.listvsset.eager.set.fulldomain;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.Table;
import java.util.Objects;
import java.util.Set;
import lombok.Data;
@Data
@Entity(name = "interest_group")
@Table(name = "interest_group")
public class Group {
@Id
private Long id;
private String name;
@ManyToMany(fetch = FetchType.EAGER)
private Set<User> members;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Group group = (Group) o;
return Objects.equals(id, group.id);
}
@Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
}

Some files were not shown because too many files have changed in this diff Show More