BAEL-6887: List vs Set in @OneToMany JPA (#15677)
This commit is contained in:
@@ -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>
|
||||
+14
@@ -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();
|
||||
}
|
||||
}
|
||||
+63
@@ -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);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.listvsset.eager.list.fulldomain;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
}
|
||||
+25
@@ -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;
|
||||
|
||||
}
|
||||
+23
@@ -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;
|
||||
}
|
||||
+32
@@ -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;
|
||||
}
|
||||
+7
@@ -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> {
|
||||
|
||||
}
|
||||
+28
@@ -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;
|
||||
}
|
||||
|
||||
+36
@@ -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;
|
||||
}
|
||||
+7
@@ -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> {
|
||||
|
||||
}
|
||||
+20
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.listvsset.eager.list.moderatedomain;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
}
|
||||
+23
@@ -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;
|
||||
}
|
||||
+7
@@ -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> {
|
||||
|
||||
}
|
||||
+29
@@ -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);
|
||||
}
|
||||
}
|
||||
+23
@@ -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;
|
||||
}
|
||||
+7
@@ -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> {
|
||||
|
||||
}
|
||||
+46
@@ -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;
|
||||
}
|
||||
}
|
||||
+7
@@ -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> {
|
||||
|
||||
}
|
||||
+20
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.listvsset.eager.list.simpledomain;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
}
|
||||
+23
@@ -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;
|
||||
}
|
||||
+7
@@ -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> {
|
||||
|
||||
}
|
||||
+26
@@ -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;
|
||||
}
|
||||
+9
@@ -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> {
|
||||
|
||||
}
|
||||
+20
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.listvsset.eager.set.fulldomain;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
}
|
||||
+44
@@ -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;
|
||||
}
|
||||
}
|
||||
+43
@@ -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
Reference in New Issue
Block a user