BAEL-6887: List vs Set in @OneToMany JPA (#15677)
This commit is contained in:
parent
9801f1eb7d
commit
9aa37e2746
|
@ -42,6 +42,26 @@
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -58,6 +78,10 @@
|
||||||
<junit-jupiter.version>5.9.3</junit-jupiter.version>
|
<junit-jupiter.version>5.9.3</junit-jupiter.version>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<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>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
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 Set<Comment> comments;
|
||||||
|
|
||||||
|
@JsonBackReference
|
||||||
|
@ManyToOne
|
||||||
|
private User author;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Post post = (Post) o;
|
||||||
|
|
||||||
|
return Objects.equals(id, post.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id != null ? id.hashCode() : 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.fulldomain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface PostRepository extends JpaRepository<Post, Long> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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,56 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
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 Set<Post> posts;
|
||||||
|
|
||||||
|
|
||||||
|
@ManyToMany(mappedBy = "members", fetch = FetchType.EAGER)
|
||||||
|
private Set<Group> groups;
|
||||||
|
|
||||||
|
@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.set.fulldomain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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.set.moderatedomain;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.moderatedomain;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.ManyToMany;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
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;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.moderatedomain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface GroupRepository extends JpaRepository<Group, Long> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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 void save(Group group) {
|
||||||
|
groupRepository.save(group);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.moderatedomain;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Lob;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
public class Post {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@JsonBackReference
|
||||||
|
@ManyToOne
|
||||||
|
private User author;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Post post = (Post) o;
|
||||||
|
|
||||||
|
return Objects.equals(id, post.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id != null ? id.hashCode() : 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.moderatedomain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface PostRepository extends JpaRepository<Post, Long> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
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 Set<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.set.moderatedomain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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.set.simpledomain;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.simpledomain;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonBackReference;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Lob;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import java.util.Objects;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Data
|
||||||
|
public class Post {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
@JsonBackReference
|
||||||
|
@ManyToOne
|
||||||
|
private User author;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Post post = (Post) o;
|
||||||
|
|
||||||
|
return Objects.equals(id, post.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id != null ? id.hashCode() : 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.simpledomain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface PostRepository extends JpaRepository<Post, Long> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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.Set;
|
||||||
|
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 Set<Post> posts;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.listvsset.eager.set.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.set.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,76 @@
|
||||||
|
package com.baeldung.listvsset;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.util.DatabaseUtil;
|
||||||
|
import com.baeldung.listvsset.util.JsonUtils;
|
||||||
|
import io.hypersistence.utils.jdbc.validator.SQLStatementCountValidator;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(properties = {
|
||||||
|
"spring.jpa.generate-ddl=true",
|
||||||
|
"spring.jpa.show-sql=false",
|
||||||
|
"spring.datasource.url=jdbc:h2:mem:~/test;DATABASE_TO_UPPER=false"
|
||||||
|
})
|
||||||
|
abstract public class BaseNPlusOneIntegrationTest<T> extends ParametrizationAware<T> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected List<Service<?>> services;
|
||||||
|
@Autowired
|
||||||
|
protected DatabaseUtil databaseUtil;
|
||||||
|
@Autowired
|
||||||
|
protected JsonUtils jsonUtils;
|
||||||
|
|
||||||
|
private final Map<Class<?>, Service<?>> serviceMap = new HashMap<>();
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
void init() {
|
||||||
|
for (Service<?> service : services) {
|
||||||
|
Class<?> parametrization = service.getParametrizationClass().get(0);
|
||||||
|
serviceMap.put(parametrization, service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
addUsers();
|
||||||
|
SQLStatementCountValidator.reset();
|
||||||
|
System.out.println("************************************************");
|
||||||
|
System.out.println("\n\n\n\n\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
System.out.println("\n\n\n\n\n");
|
||||||
|
System.out.println("************************************************");
|
||||||
|
databaseUtil.truncateAllTables();
|
||||||
|
SQLStatementCountValidator.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenCorrectConfigurationWhenStartContextThenRepositoryIsPresent() {
|
||||||
|
assertThat(getService()).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenCorrectDatabaseWhenStartThenDatabaseIsNotEmpty() {
|
||||||
|
List<?> result = getService().findAll();
|
||||||
|
assertThat(result).isNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Service<T> getService() {
|
||||||
|
Class<T> parametrization = getParametrizationClass().get(0);
|
||||||
|
return (Service<T>) serviceMap.get(parametrization);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void addUsers();
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.baeldung.listvsset;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Application;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Comment;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Group;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Post;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Profile;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.User;
|
||||||
|
import com.baeldung.listvsset.util.JsonUtils;
|
||||||
|
import com.baeldung.listvsset.util.TestConfig;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = {Application.class, TestConfig.class})
|
||||||
|
class JsonUtilTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JsonUtils jsonUtils;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenFileWhenConvertingToUsersThenConversionIsCorrect() {
|
||||||
|
List<User> users = jsonUtils.getUsers(User.class);
|
||||||
|
assertThat(users).isNotEmpty();
|
||||||
|
boolean wentThroughEverything = false;
|
||||||
|
for (User user : users) {
|
||||||
|
assertThat(user.getGroups()).isNotNull();
|
||||||
|
Profile profile = user.getProfile();
|
||||||
|
if (profile != null) {
|
||||||
|
assertThat(user.getId()).isEqualTo(profile.getUser().getId());
|
||||||
|
}
|
||||||
|
for (Post post : user.getPosts()) {
|
||||||
|
assertThat(user.getId()).isEqualTo(post.getAuthor().getId());
|
||||||
|
if (post.getComments() != null) {
|
||||||
|
wentThroughEverything = true;
|
||||||
|
for (Comment comment : post.getComments()) {
|
||||||
|
assertThat(post.getId()).isEqualTo(comment.getPost().getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(wentThroughEverything);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenFileWhenConvertingToGroupsThenConversionIsCorrect() {
|
||||||
|
List<Group> groups = jsonUtils.getGroups(Group.class);
|
||||||
|
assertThat(groups).isNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.baeldung.listvsset.list;
|
||||||
|
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.BaseNPlusOneIntegrationTest;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Application;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Comment;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Group;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.Post;
|
||||||
|
import com.baeldung.listvsset.eager.list.fulldomain.User;
|
||||||
|
import com.baeldung.listvsset.util.TestConfig;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.ToIntFunction;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = {
|
||||||
|
"hibernate.show_sql=true",
|
||||||
|
"logging.level.org.hibernate.SQL=debug",
|
||||||
|
"logging.level.org.hibernate.orm.jdbc.bind=trace"
|
||||||
|
})
|
||||||
|
class NPlusOneEagerFullDomainIntegrationTest extends BaseNPlusOneIntegrationTest<User> {
|
||||||
|
|
||||||
|
public static final String POSTS = "posts";
|
||||||
|
public static final String USERS = "users";
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
void givenEagerListBasedUser_WhenFetchingAllUsers_ThenIssueNPlusOneRequests(ToIntFunction<List<User>> function) {
|
||||||
|
int numberOfRequests = getService().countNumberOfRequestsWithFunction(function);
|
||||||
|
assertSelectCount(numberOfRequests);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Stream<Arguments> givenEagerListBasedUser_WhenFetchingAllUsers_ThenIssueNPlusOneRequests() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of((ToIntFunction<List<User>>) s -> {
|
||||||
|
int result = 2 * s.size() + 1;
|
||||||
|
List<Post> posts = s.stream().map(User::getPosts)
|
||||||
|
.flatMap(List::stream)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
result += posts.size();
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedUser_WhenFetchingOneUser_ThenUseDFS(Long id) {
|
||||||
|
int numberOfRequests = getService().getUserByIdWithFunction(id, this::countNumberOfRequests);
|
||||||
|
assertSelectCount(numberOfRequests);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countNumberOfRequests(User user) {
|
||||||
|
HashMap<String, Set<Long>> visitedMap = new HashMap<>();
|
||||||
|
visitedMap.put(POSTS, new HashSet<>());
|
||||||
|
visitedMap.put(USERS, new HashSet<>());
|
||||||
|
int result = 1;
|
||||||
|
visitedMap.get(USERS).add(user.getId());
|
||||||
|
List<Post> posts = user.getPosts();
|
||||||
|
result += 1;
|
||||||
|
result += explorePosts(posts, visitedMap);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private int explorePosts(List<Post> posts, HashMap<String, Set<Long>> visitedMap) {
|
||||||
|
int result = 0;
|
||||||
|
if (posts == null || posts.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (Post post : posts) {
|
||||||
|
if (!visitedMap.get(POSTS).contains(post.getId())) {
|
||||||
|
result++;
|
||||||
|
visitedMap.get(POSTS).add(post.getId());
|
||||||
|
List<User> commenters = post.getComments().stream().map(Comment::getAuthor).toList();
|
||||||
|
result += exploreUsers(commenters, visitedMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int exploreUsers(List<User> users, HashMap<String, Set<Long>> visitedMap) {
|
||||||
|
int result = 0;
|
||||||
|
if (users == null || users.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (User user : users) {
|
||||||
|
if (!visitedMap.get(USERS).contains(user.getId())) {
|
||||||
|
++result;
|
||||||
|
visitedMap.get(USERS).add(user.getId());
|
||||||
|
result += explorePosts(user.getPosts(), visitedMap);
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addUsers() {
|
||||||
|
List<Group> groups = jsonUtils.getGroups(Group.class);
|
||||||
|
databaseUtil.saveAll(groups);
|
||||||
|
List<User> users = jsonUtils.getUsers(User.class);
|
||||||
|
Map<Long, List<Comment>> comments = new HashMap<>();
|
||||||
|
for (User user : users) {
|
||||||
|
for (Post post : user.getPosts()) {
|
||||||
|
if (!comments.containsKey(post.getId())) {
|
||||||
|
comments.put(post.getId(), new ArrayList<>());
|
||||||
|
}
|
||||||
|
comments.get(post.getId()).addAll(post.getComments());
|
||||||
|
post.setComments(Collections.emptyList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
databaseUtil.saveAll(users);
|
||||||
|
// Handle non-existent users while adding comments
|
||||||
|
databaseUtil.mergeAll(jsonUtils.getUsers(User.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.baeldung.listvsset.list;
|
||||||
|
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertDeleteCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertInsertCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.reset;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.BaseNPlusOneIntegrationTest;
|
||||||
|
import com.baeldung.listvsset.eager.list.moderatedomain.Application;
|
||||||
|
import com.baeldung.listvsset.eager.list.moderatedomain.Group;
|
||||||
|
import com.baeldung.listvsset.eager.list.moderatedomain.GroupService;
|
||||||
|
import com.baeldung.listvsset.eager.list.moderatedomain.User;
|
||||||
|
import com.baeldung.listvsset.util.TestConfig;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = {
|
||||||
|
"hibernate.show_sql=true",
|
||||||
|
"logging.level.org.hibernate.SQL=debug",
|
||||||
|
"logging.level.org.hibernate.orm.jdbc.bind=trace"
|
||||||
|
})
|
||||||
|
class NPlusOneEagerModerateDomainIntegrationTest extends BaseNPlusOneIntegrationTest<User> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GroupService groupService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenEagerListBasedUser_whenFetchingAllUsers_thenIssueNPlusOneRequests() {
|
||||||
|
List<User> users = getService().findAll();
|
||||||
|
assertSelectCount(users.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedUser_whenFetchingOneUser_thenIssueOneRequest(Long id) {
|
||||||
|
getService().getUserById(id);
|
||||||
|
assertSelectCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenEagerListBasedGroup_whenFetchingAllGroups_thenIssueNPlusMPlusOneRequests() {
|
||||||
|
List<Group> groups = groupService.findAll();
|
||||||
|
Set<User> users = groups.stream().map(Group::getMembers).flatMap(List::stream).collect(Collectors.toSet());
|
||||||
|
assertSelectCount(groups.size() + users.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedGroup_whenFetchingAllGroups_thenIssueNPlusOneRequests(Long groupId) {
|
||||||
|
Optional<Group> group = groupService.findById(groupId);
|
||||||
|
assertThat(group).isPresent();
|
||||||
|
assertSelectCount(1 + group.get().getMembers().size());
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedGroup_whenRemoveUser_thenRecreateGroup(Long groupId) {
|
||||||
|
Optional<Group> optionalGroup = groupService.findById(groupId);
|
||||||
|
assertThat(optionalGroup).isPresent();
|
||||||
|
Group group = optionalGroup.get();
|
||||||
|
List<User> members = group.getMembers();
|
||||||
|
assertSelectCount(1 + members.size());
|
||||||
|
if (!members.isEmpty()) {
|
||||||
|
reset();
|
||||||
|
members.remove(0);
|
||||||
|
groupService.save(group);
|
||||||
|
assertSelectCount(1 + members.size() + 1);
|
||||||
|
assertDeleteCount(1);
|
||||||
|
assertInsertCount(members.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addUsers() {
|
||||||
|
List<User> users = jsonUtils.getUsers(User.class);
|
||||||
|
databaseUtil.saveAll(users);
|
||||||
|
List<Group> groups = jsonUtils.getGroupsWithMembers(Group.class);
|
||||||
|
databaseUtil.saveAll(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.baeldung.listvsset.list;
|
||||||
|
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertUpdateCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.reset;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.BaseNPlusOneIntegrationTest;
|
||||||
|
import com.baeldung.listvsset.eager.list.simpledomain.Application;
|
||||||
|
import com.baeldung.listvsset.eager.list.simpledomain.Post;
|
||||||
|
import com.baeldung.listvsset.eager.list.simpledomain.User;
|
||||||
|
import com.baeldung.listvsset.util.TestConfig;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = {
|
||||||
|
"hibernate.show_sql=true",
|
||||||
|
"logging.level.org.hibernate.SQL=debug",
|
||||||
|
"logging.level.org.hibernate.orm.jdbc.bind=trace"
|
||||||
|
})
|
||||||
|
class NPlusOneEagerSimpleDomainIntegrationTest extends BaseNPlusOneIntegrationTest<User> {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenEagerListBasedUser_WhenFetchingAllUsers_ThenIssueNPlusOneRequests() {
|
||||||
|
List<User> users = getService().findAll();
|
||||||
|
assertSelectCount(users.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedUser_WhenFetchingOneUser_ThenIssueOneRequest(Long id) {
|
||||||
|
getService().getUserById(id);
|
||||||
|
assertSelectCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedUser_whenDeletePost_ThenIssueSingleUpdate(Long id) {
|
||||||
|
Optional<User> optionalUser = getService().getUserById(id);
|
||||||
|
assertSelectCount(1);
|
||||||
|
optionalUser.ifPresent(user -> {
|
||||||
|
List<Post> posts = user.getPosts();
|
||||||
|
int originalNumberOfPosts = posts.size();
|
||||||
|
reset();
|
||||||
|
if (!posts.isEmpty()) {
|
||||||
|
posts.get(0).setAuthor(null);
|
||||||
|
getService().save(user);
|
||||||
|
assertSelectCount(1);
|
||||||
|
assertUpdateCount(1);
|
||||||
|
getService().getUserById(id).ifPresent(updatedUser -> {
|
||||||
|
assertThat(updatedUser.getPosts()).hasSize(originalNumberOfPosts - 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addUsers() {
|
||||||
|
List<User> users = jsonUtils.getUsers(User.class);
|
||||||
|
databaseUtil.saveAll(users);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
package com.baeldung.listvsset.set;
|
||||||
|
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.BaseNPlusOneIntegrationTest;
|
||||||
|
import com.baeldung.listvsset.eager.set.fulldomain.Application;
|
||||||
|
import com.baeldung.listvsset.eager.set.fulldomain.Comment;
|
||||||
|
import com.baeldung.listvsset.eager.set.fulldomain.Group;
|
||||||
|
import com.baeldung.listvsset.eager.set.fulldomain.Post;
|
||||||
|
import com.baeldung.listvsset.eager.set.fulldomain.User;
|
||||||
|
import com.baeldung.listvsset.util.TestConfig;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = {
|
||||||
|
"hibernate.show_sql=true",
|
||||||
|
"logging.level.org.hibernate.SQL=debug",
|
||||||
|
"logging.level.org.hibernate.orm.jdbc.bind=trace"
|
||||||
|
})
|
||||||
|
class NPlusOneEagerFullDomainJoinIntegrationTest extends BaseNPlusOneIntegrationTest<User> {
|
||||||
|
|
||||||
|
public static final String POSTS = "posts";
|
||||||
|
public static final String USERS = "users";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenEagerSetBasedUser_WhenFetchingAllUsers_ThenIssueNPlusOneRequests() {
|
||||||
|
List<User> users = getService().findAll();
|
||||||
|
assertSelectCount(users.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerUserWhenFetchingOneUserThenIssueNPlusOneRequestsWithCartesianProduct(Long id) {
|
||||||
|
HashMap<String, Set<Long>> visitedMap = new HashMap<>();
|
||||||
|
visitedMap.put(POSTS, new HashSet<>());
|
||||||
|
visitedMap.put(USERS, new HashSet<>());
|
||||||
|
int numberOfRequests = getService()
|
||||||
|
.getUserByIdWithFunction(id, user -> {
|
||||||
|
int result = 1;
|
||||||
|
visitedMap.get(USERS).add(user.getId());
|
||||||
|
Set<Post> posts = user.getPosts();
|
||||||
|
result += explorePosts(posts, visitedMap);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
assertSelectCount(numberOfRequests);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int explorePosts(Set<Post> posts, HashMap<String, Set<Long>> visitedMap) {
|
||||||
|
int result = 0;
|
||||||
|
if (posts == null || posts.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (Post post : posts) {
|
||||||
|
if (!visitedMap.get(POSTS).contains(post.getId())) {
|
||||||
|
visitedMap.get(POSTS).add(post.getId());
|
||||||
|
List<User> commenters = post.getComments().stream().map(Comment::getAuthor).toList();
|
||||||
|
result += exploreUsers(commenters, visitedMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int exploreUsers(List<User> users, HashMap<String, Set<Long>> visitedMap) {
|
||||||
|
int result = 0;
|
||||||
|
if (users == null || users.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (User user : users) {
|
||||||
|
if (!visitedMap.get(USERS).contains(user.getId())) {
|
||||||
|
++result;
|
||||||
|
visitedMap.get(USERS).add(user.getId());
|
||||||
|
result += explorePosts(user.getPosts(), visitedMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addUsers() {
|
||||||
|
List<Group> groups = jsonUtils.getGroups(Group.class);
|
||||||
|
databaseUtil.saveAll(groups);
|
||||||
|
List<User> users = jsonUtils.getUsers(User.class);
|
||||||
|
Map<Long, List<Comment>> comments = new HashMap<>();
|
||||||
|
for (User user : users) {
|
||||||
|
for (Post post : user.getPosts()) {
|
||||||
|
if (!comments.containsKey(post.getId())) {
|
||||||
|
comments.put(post.getId(), new ArrayList<>());
|
||||||
|
}
|
||||||
|
comments.get(post.getId()).addAll(post.getComments());
|
||||||
|
post.setComments(Collections.emptySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
databaseUtil.saveAll(users);
|
||||||
|
// Handle non-existent users while adding comments
|
||||||
|
databaseUtil.mergeAll(jsonUtils.getUsers(User.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.baeldung.listvsset.set;
|
||||||
|
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertDeleteCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.reset;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.BaseNPlusOneIntegrationTest;
|
||||||
|
import com.baeldung.listvsset.eager.set.moderatedomain.Application;
|
||||||
|
import com.baeldung.listvsset.eager.set.moderatedomain.Group;
|
||||||
|
import com.baeldung.listvsset.eager.set.moderatedomain.GroupService;
|
||||||
|
import com.baeldung.listvsset.eager.set.moderatedomain.User;
|
||||||
|
import com.baeldung.listvsset.util.TestConfig;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = {
|
||||||
|
"hibernate.show_sql=true",
|
||||||
|
"logging.level.org.hibernate.SQL=debug",
|
||||||
|
"logging.level.org.hibernate.orm.jdbc.bind=trace"
|
||||||
|
})
|
||||||
|
class NPlusOneEagerModerateDomainIntegrationTest extends BaseNPlusOneIntegrationTest<User> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GroupService groupService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenEagerSetBasedUser_whenFetchingAllUsers_thenIssueNPlusOneRequests() {
|
||||||
|
List<User> users = getService().findAll();
|
||||||
|
assertSelectCount(users.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerSetBasedUser_whenFetchingOneUser_thenIssueOneRequest(Long id) {
|
||||||
|
getService().getUserById(id);
|
||||||
|
assertSelectCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenEagerSetBasedGroup_whenFetchingAllGroups_thenIssueNPlusOneRequests() {
|
||||||
|
List<Group> groups = groupService.findAll();
|
||||||
|
assertSelectCount(groups.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerSetBasedGroup_whenFetchingAllGroups_thenCreateCartesianProductInOneQuery(Long groupId) {
|
||||||
|
groupService.findById(groupId);
|
||||||
|
assertSelectCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedGroup_whenRemoveUser_thenIssueOnlyOneDelete(Long groupId) {
|
||||||
|
Optional<Group> optionalGroup = groupService.findById(groupId);
|
||||||
|
assertThat(optionalGroup).isPresent();
|
||||||
|
Group group = optionalGroup.get();
|
||||||
|
if (!group.getMembers().isEmpty()) {
|
||||||
|
reset();
|
||||||
|
Set<User> newMembers = group.getMembers().stream().skip(1).collect(Collectors.toSet());
|
||||||
|
group.setMembers(newMembers);
|
||||||
|
groupService.save(group);
|
||||||
|
assertSelectCount(1);
|
||||||
|
assertDeleteCount(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addUsers() {
|
||||||
|
List<User> users = jsonUtils.getUsers(User.class);
|
||||||
|
databaseUtil.saveAll(users);
|
||||||
|
List<Group> groups = jsonUtils.getGroupsWithMembers(Group.class);
|
||||||
|
databaseUtil.saveAll(groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.baeldung.listvsset.set;
|
||||||
|
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertUpdateCount;
|
||||||
|
import static com.vladmihalcea.sql.SQLStatementCountValidator.reset;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.baeldung.listvsset.BaseNPlusOneIntegrationTest;
|
||||||
|
import com.baeldung.listvsset.eager.set.simpledomain.Application;
|
||||||
|
import com.baeldung.listvsset.eager.set.simpledomain.Post;
|
||||||
|
import com.baeldung.listvsset.eager.set.simpledomain.User;
|
||||||
|
import com.baeldung.listvsset.util.TestConfig;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = {
|
||||||
|
"hibernate.show_sql=true",
|
||||||
|
"logging.level.org.hibernate.SQL=debug",
|
||||||
|
"logging.level.org.hibernate.orm.jdbc.bind=trace"
|
||||||
|
})
|
||||||
|
class NPlusOneEagerSimpleDomainIntegrationTest extends BaseNPlusOneIntegrationTest<User> {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenEagerSetBasedUser_WhenFetchingAllUsers_ThenIssueNPlusOneRequests() {
|
||||||
|
List<User> users = getService().findAll();
|
||||||
|
assertSelectCount(users.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerSetBasedUser_WhenFetchingOneUser_ThenIssueOneRequest(Long id) {
|
||||||
|
getService().getUserById(id);
|
||||||
|
assertSelectCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
||||||
|
void givenEagerListBasedUser_whenDeletePost_ThenIssueSingleUpdate(Long id) {
|
||||||
|
Optional<User> optionalUser = getService().getUserById(id);
|
||||||
|
assertSelectCount(1);
|
||||||
|
optionalUser.ifPresent(user -> {
|
||||||
|
Set<Post> posts = user.getPosts();
|
||||||
|
int originalNumberOfPosts = posts.size();
|
||||||
|
reset();
|
||||||
|
if (!posts.isEmpty()) {
|
||||||
|
posts.iterator().next().setAuthor(null);
|
||||||
|
getService().save(user);
|
||||||
|
assertSelectCount(1);
|
||||||
|
assertUpdateCount(1);
|
||||||
|
getService().getUserById(id).ifPresent(updatedUser -> {
|
||||||
|
assertThat(updatedUser.getPosts()).hasSize(originalNumberOfPosts - 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addUsers() {
|
||||||
|
List<User> users = jsonUtils.getUsers(User.class);
|
||||||
|
databaseUtil.saveAll(users);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.listvsset.util;
|
||||||
|
|
||||||
|
import io.hypersistence.utils.logging.InlineQueryLogEntryCreator;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import net.ttddyy.dsproxy.listener.ChainListener;
|
||||||
|
import net.ttddyy.dsproxy.listener.DataSourceQueryCountListener;
|
||||||
|
import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener;
|
||||||
|
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DataSourceWrapper implements BeanPostProcessor {
|
||||||
|
|
||||||
|
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
if (bean instanceof DataSource originalDataSource) {
|
||||||
|
ChainListener listener = new ChainListener();
|
||||||
|
SLF4JQueryLoggingListener loggingListener = new SLF4JQueryLoggingListener();
|
||||||
|
loggingListener.setQueryLogEntryCreator(new InlineQueryLogEntryCreator());
|
||||||
|
listener.addListener(loggingListener);
|
||||||
|
listener.addListener(new DataSourceQueryCountListener());
|
||||||
|
return ProxyDataSourceBuilder
|
||||||
|
.create(originalDataSource)
|
||||||
|
.name("DS-Proxy")
|
||||||
|
.listener(listener)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.baeldung.listvsset.util;
|
||||||
|
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.PersistenceContext;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DatabaseUtil {
|
||||||
|
|
||||||
|
public static final String TRUNCATE_QUERY_FORMAT = "TRUNCATE TABLE %s";
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void truncateAllTables() {
|
||||||
|
switchForeignKeysOff();
|
||||||
|
entityManager.createNativeQuery("SHOW TABLES", String.class)
|
||||||
|
.getResultList()
|
||||||
|
.forEach(this::truncateTable);
|
||||||
|
switchForeignKeysOn();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public <T> void saveAll(List<T> entities) {
|
||||||
|
entities.forEach(s -> entityManager.persist(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public <T> void mergeAll(List<T> entities) {
|
||||||
|
entities.forEach(s -> entityManager.merge(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int truncateTable(Object s) {
|
||||||
|
return entityManager
|
||||||
|
.createNativeQuery(TRUNCATE_QUERY_FORMAT.formatted(s)).executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchForeignKeysOn() {
|
||||||
|
entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchForeignKeysOff() {
|
||||||
|
entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.baeldung.listvsset.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JsonUtils {
|
||||||
|
|
||||||
|
@Value("users.json")
|
||||||
|
private File userFile;
|
||||||
|
|
||||||
|
@Value("groups.json")
|
||||||
|
private File groupFile;
|
||||||
|
|
||||||
|
@Value("groups_with_members.json")
|
||||||
|
private File groupsWithMembersFile;
|
||||||
|
|
||||||
|
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
|
static {
|
||||||
|
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> getUsers(Class<T> userType) {
|
||||||
|
return getObjects(userType, userFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> getGroups(Class<T> userType) {
|
||||||
|
return getObjects(userType, groupFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> List<T> getGroupsWithMembers(Class<T> groupType) {
|
||||||
|
return getObjects(groupType, groupsWithMembersFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> List<T> getObjects(Class<T> userType, File userFile1) {
|
||||||
|
try {
|
||||||
|
return MAPPER.readValue(userFile1, MAPPER.getTypeFactory()
|
||||||
|
.constructCollectionType(List.class, userType));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.baeldung.listvsset.util;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class TestConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSourceWrapper dataSourceWrapper() {
|
||||||
|
return new DataSourceWrapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DatabaseUtil databaseUtil() {
|
||||||
|
return new DatabaseUtil();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JsonUtils jsonUtils() {
|
||||||
|
return new JsonUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,402 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Bitwolf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Solarbreeze"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Bamity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"name": "Hatity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"name": "Veribet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"name": "Tampflex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"name": "Zontrax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"name": "Aerified"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"name": "Konklab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"name": "Tampflex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"name": "Mat Lam Tam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"name": "Alpha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"name": "Quo Lux"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"name": "Kanlam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"name": "Veribet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"name": "Ventosanzap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"name": "Opela"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 18,
|
||||||
|
"name": "Alphazap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 19,
|
||||||
|
"name": "Lotlux"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 20,
|
||||||
|
"name": "Alpha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 21,
|
||||||
|
"name": "Andalax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 22,
|
||||||
|
"name": "Bitchip"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 23,
|
||||||
|
"name": "Cookley"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 24,
|
||||||
|
"name": "Konklab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 25,
|
||||||
|
"name": "Konklab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 26,
|
||||||
|
"name": "Lotstring"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 27,
|
||||||
|
"name": "Konklux"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 28,
|
||||||
|
"name": "Temp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 29,
|
||||||
|
"name": "Voyatouch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 30,
|
||||||
|
"name": "Trippledex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 31,
|
||||||
|
"name": "Sonsing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 32,
|
||||||
|
"name": "Andalax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 33,
|
||||||
|
"name": "Voltsillam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 34,
|
||||||
|
"name": "Stronghold"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 35,
|
||||||
|
"name": "Hatity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 36,
|
||||||
|
"name": "Andalax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 37,
|
||||||
|
"name": "Holdlamis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 38,
|
||||||
|
"name": "Bamity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 39,
|
||||||
|
"name": "Voltsillam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 40,
|
||||||
|
"name": "Aerified"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 41,
|
||||||
|
"name": "Regrant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 42,
|
||||||
|
"name": "Subin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 43,
|
||||||
|
"name": "Tin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 44,
|
||||||
|
"name": "Voltsillam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 45,
|
||||||
|
"name": "Trippledex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 46,
|
||||||
|
"name": "Solarbreeze"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 47,
|
||||||
|
"name": "Treeflex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 48,
|
||||||
|
"name": "Fintone"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 49,
|
||||||
|
"name": "Tin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 50,
|
||||||
|
"name": "It"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 51,
|
||||||
|
"name": "Y-Solowarm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 52,
|
||||||
|
"name": "Bigtax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 53,
|
||||||
|
"name": "Flowdesk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 54,
|
||||||
|
"name": "Vagram"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55,
|
||||||
|
"name": "Keylex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 56,
|
||||||
|
"name": "Zontrax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57,
|
||||||
|
"name": "Vagram"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 58,
|
||||||
|
"name": "Lotstring"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 59,
|
||||||
|
"name": "Cookley"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 60,
|
||||||
|
"name": "Zaam-Dox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 61,
|
||||||
|
"name": "Zoolab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 62,
|
||||||
|
"name": "Quo Lux"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 63,
|
||||||
|
"name": "Ventosanzap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 64,
|
||||||
|
"name": "Ventosanzap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 65,
|
||||||
|
"name": "Lotstring"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 66,
|
||||||
|
"name": "Keylex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 67,
|
||||||
|
"name": "Stim"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 68,
|
||||||
|
"name": "Alphazap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 69,
|
||||||
|
"name": "It"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 70,
|
||||||
|
"name": "Cardify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 71,
|
||||||
|
"name": "Zamit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 72,
|
||||||
|
"name": "Holdlamis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 73,
|
||||||
|
"name": "Konklab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 74,
|
||||||
|
"name": "Ventosanzap"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 75,
|
||||||
|
"name": "Wrapsafe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 76,
|
||||||
|
"name": "Cookley"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 77,
|
||||||
|
"name": "Y-find"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 78,
|
||||||
|
"name": "Regrant"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 79,
|
||||||
|
"name": "Otcom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 80,
|
||||||
|
"name": "Cookley"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 81,
|
||||||
|
"name": "Bigtax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 82,
|
||||||
|
"name": "Holdlamis"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 83,
|
||||||
|
"name": "Bigtax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 84,
|
||||||
|
"name": "Voltsillam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 85,
|
||||||
|
"name": "Duobam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 86,
|
||||||
|
"name": "Flowdesk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 87,
|
||||||
|
"name": "It"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 88,
|
||||||
|
"name": "Hatity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 89,
|
||||||
|
"name": "Zathin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 90,
|
||||||
|
"name": "Hatity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 91,
|
||||||
|
"name": "Cardify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 92,
|
||||||
|
"name": "Konklab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 93,
|
||||||
|
"name": "Treeflex"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 94,
|
||||||
|
"name": "Flexidy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 95,
|
||||||
|
"name": "Latlux"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 96,
|
||||||
|
"name": "Bitwolf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 97,
|
||||||
|
"name": "Zontrax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 98,
|
||||||
|
"name": "Greenlam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 99,
|
||||||
|
"name": "Asoka"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 100,
|
||||||
|
"name": "Ronstring"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,183 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Pacocha-Hills",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Windler, Wiegand and Bernhard",
|
||||||
|
"members": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Flatley-Hilll",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"name": "Daugherty and Sons",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"name": "Leannon, Kub and Murazik",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"name": "Considine-Koss",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"name": "Russel LLC",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"name": "Wisoky-Grimes",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"name": "Larson Inc",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"name": "Franecki-Simonis",
|
||||||
|
"members": []
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,899 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"username": "ecrumbleholme0",
|
||||||
|
"email": "pmerritt0@wordpress.org",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 67
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 54
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 41
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 82
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 1,
|
||||||
|
"biography": "Mauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.",
|
||||||
|
"website": "https://engadget.com/adipiscing/lorem/vitae/mattis.jpg?non=in&mattis=porttitor&pulvinar=pede&nulla",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/207x100.png/dddddd/000000"
|
||||||
|
},
|
||||||
|
"posts": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"username": "moldred1",
|
||||||
|
"email": "grichardes1@shareasale.com",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 39
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 53
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 26
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 49
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 33
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 64
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 65
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 2,
|
||||||
|
"biography": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin risus. Praesent lectus.",
|
||||||
|
"website": "http://arizona.edu/urna/ut.html?erat=pretium&volutpat=iaculis&in=diam&congue",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/200x100.png/dddddd/000000"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"content": "Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 208446,
|
||||||
|
"test": {
|
||||||
|
"id": "Optional empowering attitude"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 229466,
|
||||||
|
"test": {
|
||||||
|
"id": "Customizable multi-tasking encryption"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 408703,
|
||||||
|
"test": {
|
||||||
|
"id": "Re-engineered contextually-based protocol"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 837433,
|
||||||
|
"test": {
|
||||||
|
"id": "Centralized well-modulated pricing structure"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"content": "Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.",
|
||||||
|
"comments": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"content": "Vestibulum quam sapien, varius ut, blandit non, interdum in, ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Duis faucibus accumsan odio. Curabitur convallis.\n\nDuis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.\n\nMauris enim leo, rhoncus sed, vestibulum sit amet, cursus id, turpis. Integer aliquet, massa id lobortis convallis, tortor risus dapibus augue, vel accumsan tellus nisi eu orci. Mauris lacinia sapien quis libero.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 53333,
|
||||||
|
"test": {
|
||||||
|
"id": "Cross-platform bi-directional encoding"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 806260,
|
||||||
|
"test": {
|
||||||
|
"id": "Expanded composite neural-net"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 266068,
|
||||||
|
"test": {
|
||||||
|
"id": "Implemented attitude-oriented knowledge user"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"username": "agoodsall2",
|
||||||
|
"email": "ofellman2@ibm.com",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 36
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 77
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 28
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 32
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 3,
|
||||||
|
"biography": "In hac habitasse platea dictumst. Morbi vestibulum, velit id pretium iaculis, diam erat fermentum justo, nec condimentum neque sapien placerat ante. Nulla justo.",
|
||||||
|
"website": "http://cargocollective.com/consequat/in/consequat/ut/nulla/sed.png?dictumst=faucibus",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/224x100.png/cc0000/ffffff"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"content": "Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.\n\nCurabitur at ipsum ac tellus semper interdum. Mauris ullamcorper purus sit amet nulla. Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 349493,
|
||||||
|
"test": {
|
||||||
|
"id": "Operative actuating budgetary management"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 909598,
|
||||||
|
"test": {
|
||||||
|
"id": "Profound next generation product"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 247072,
|
||||||
|
"test": {
|
||||||
|
"id": "Team-oriented multimedia analyzer"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"content": "Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 572489,
|
||||||
|
"test": {
|
||||||
|
"id": "Open-source optimizing focus group"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 133947,
|
||||||
|
"test": {
|
||||||
|
"id": "Self-enabling attitude-oriented success"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 496573,
|
||||||
|
"test": {
|
||||||
|
"id": "Profit-focused multimedia firmware"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 137780,
|
||||||
|
"test": {
|
||||||
|
"id": "Self-enabling intermediate info-mediaries"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"content": "Maecenas tristique, est et tempus semper, est quam pharetra magna, ac consequat metus sapien ut nunc. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Mauris viverra diam vitae quam. Suspendisse potenti.\n\nNullam porttitor lacus at turpis. Donec posuere metus vitae ipsum. Aliquam non mauris.",
|
||||||
|
"comments": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"username": "cpourvoieur3",
|
||||||
|
"email": "mlisimore3@unicef.org",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 27
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 49
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 48
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 57
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 19
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 4,
|
||||||
|
"biography": "Curabitur gravida nisi at nibh. In hac habitasse platea dictumst. Aliquam augue quam, sollicitudin vitae, consectetuer eget, rutrum at, lorem.",
|
||||||
|
"website": "http://slideshare.net/rutrum/nulla/tellus/in/sagittis/dui.png?duis=volutpat&at=erat",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/167x100.png/cc0000/ffffff"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"content": "Vestibulum ac est lacinia nisi venenatis tristique. Fusce congue, diam id ornare imperdiet, sapien urna pretium nisl, ut volutpat sapien arcu sed augue. Aliquam erat volutpat.\n\nIn congue. Etiam justo. Etiam pretium iaculis justo.\n\nIn hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.",
|
||||||
|
"comments": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"content": "Sed ante. Vivamus tortor. Duis mattis egestas metus.\n\nAenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.\n\nQuisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.",
|
||||||
|
"comments": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"content": "Duis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.\n\nDonec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.\n\nDuis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 727396,
|
||||||
|
"test": {
|
||||||
|
"id": "Business-focused maximized framework"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 529333,
|
||||||
|
"test": {
|
||||||
|
"id": "Fully-configurable client-driven Graphic Interface"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 698528,
|
||||||
|
"test": {
|
||||||
|
"id": "Diverse methodical framework"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 570927,
|
||||||
|
"test": {
|
||||||
|
"id": "Profound interactive infrastructure"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"content": "Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.\n\nAenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 374234,
|
||||||
|
"test": {
|
||||||
|
"id": "Profit-focused fresh-thinking success"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 266342,
|
||||||
|
"test": {
|
||||||
|
"id": "Advanced optimizing Graphic Interface"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 970877,
|
||||||
|
"test": {
|
||||||
|
"id": "Multi-lateral web-enabled synergy"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 635357,
|
||||||
|
"test": {
|
||||||
|
"id": "Centralized real-time time-frame"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 818761,
|
||||||
|
"test": {
|
||||||
|
"id": "Profit-focused secondary middleware"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"username": "driddoch4",
|
||||||
|
"email": "hfreake4@simplemachines.org",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 68
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 52
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 82
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 29
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 55
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 95
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 5,
|
||||||
|
"biography": "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
|
||||||
|
"website": "http://jiathis.com/turpis/enim/blandit/mi/in.html?duis=augue&mattis=vel&egestas",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/181x100.png/5fa2dd/ffffff"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"content": "Phasellus sit amet erat. Nulla tempus. Vivamus in felis eu sapien cursus vestibulum.\n\nProin eu mi. Nulla ac enim. In tempor, turpis nec euismod scelerisque, quam turpis adipiscing lorem, vitae mattis nibh ligula nec sem.\n\nDuis aliquam convallis nunc. Proin at turpis a pede posuere nonummy. Integer non velit.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 668167,
|
||||||
|
"test": {
|
||||||
|
"id": "Decentralized static application"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 645021,
|
||||||
|
"test": {
|
||||||
|
"id": "Progressive cohesive complexity"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 904836,
|
||||||
|
"test": {
|
||||||
|
"id": "Right-sized human-resource middleware"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 193482,
|
||||||
|
"test": {
|
||||||
|
"id": "Organized bottom-line monitoring"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"content": "Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 820497,
|
||||||
|
"test": {
|
||||||
|
"id": "Open-architected well-modulated structure"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"content": "Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.\n\nCras non velit nec nisi vulputate nonummy. Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque.\n\nQuisque porta volutpat erat. Quisque erat eros, viverra eget, congue eget, semper rutrum, nulla. Nunc purus.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 214834,
|
||||||
|
"test": {
|
||||||
|
"id": "Face to face content-based contingency"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 361052,
|
||||||
|
"test": {
|
||||||
|
"id": "Vision-oriented client-driven emulation"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 819369,
|
||||||
|
"test": {
|
||||||
|
"id": "Decentralized clear-thinking projection"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"content": "Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.\n\nNam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.",
|
||||||
|
"comments": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"username": "dvelte5",
|
||||||
|
"email": "shuke5@canalblog.com",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 86
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 28
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 22
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 6,
|
||||||
|
"biography": "Maecenas leo odio, condimentum id, luctus nec, molestie sed, justo. Pellentesque viverra pede ac diam. Cras pellentesque volutpat dui.",
|
||||||
|
"website": "http://amazon.co.jp/eget/semper.aspx?faucibus=habitasse&cursus=platea&urna",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/179x100.png/dddddd/000000"
|
||||||
|
},
|
||||||
|
"posts": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"username": "mhallor6",
|
||||||
|
"email": "gpetters6@tiny.cc",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 49
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 56
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 24
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 7,
|
||||||
|
"biography": "Nam ultrices, libero non mattis pulvinar, nulla pede ullamcorper augue, a suscipit nulla elit ac nulla. Sed vel enim sit amet nunc viverra dapibus. Nulla suscipit ligula in lacus.",
|
||||||
|
"website": "https://globo.com/eget/nunc.js?justo=nulla&eu=neque&massa=libero&donec=convallis&dapibus",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/122x100.png/ff4444/ffffff"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"content": "Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 380358,
|
||||||
|
"test": {
|
||||||
|
"id": "Optimized user-facing software"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"username": "nbergeau7",
|
||||||
|
"email": "mkibbel7@tmall.com",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 54
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 95
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 8,
|
||||||
|
"biography": "Suspendisse potenti. In eleifend quam a odio. In hac habitasse platea dictumst.",
|
||||||
|
"website": "http://people.com.cn/odio/consequat/varius.jsp?eros=nullam&vestibulum=varius&ac=nulla",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/230x100.png/5fa2dd/ffffff"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"content": "Pellentesque at nulla. Suspendisse potenti. Cras in purus eu magna vulputate luctus.\n\nCum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.\n\nEtiam vel augue. Vestibulum rutrum rutrum neque. Aenean auctor gravida sem.",
|
||||||
|
"comments": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 17,
|
||||||
|
"content": "Sed ante. Vivamus tortor. Duis mattis egestas metus.\n\nAenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 886087,
|
||||||
|
"test": {
|
||||||
|
"id": "Total demand-driven infrastructure"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 235353,
|
||||||
|
"test": {
|
||||||
|
"id": "Versatile mobile monitoring"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 264476,
|
||||||
|
"test": {
|
||||||
|
"id": "Future-proofed static initiative"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 18,
|
||||||
|
"content": "Praesent id massa id nisl venenatis lacinia. Aenean sit amet justo. Morbi ut odio.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 299869,
|
||||||
|
"test": {
|
||||||
|
"id": "Pre-emptive 3rd generation pricing structure"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 82649,
|
||||||
|
"test": {
|
||||||
|
"id": "Public-key holistic pricing structure"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 675757,
|
||||||
|
"test": {
|
||||||
|
"id": "Function-based homogeneous monitoring"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 321146,
|
||||||
|
"test": {
|
||||||
|
"id": "Proactive intangible ability"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 754321,
|
||||||
|
"test": {
|
||||||
|
"id": "Operative zero tolerance complexity"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"username": "ddebruin8",
|
||||||
|
"email": "zdavidovits8@aol.com",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 67
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 67
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 34
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 53
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 9,
|
||||||
|
"biography": "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus vestibulum sagittis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.",
|
||||||
|
"website": "http://shinystat.com/nec/sem/duis/aliquam/convallis/nunc.json?eget=facilisi&semper=cras",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/229x100.png/5fa2dd/ffffff"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 19,
|
||||||
|
"content": "Proin interdum mauris non ligula pellentesque ultrices. Phasellus id sapien in sapien iaculis congue. Vivamus metus arcu, adipiscing molestie, hendrerit at, vulputate vitae, nisl.\n\nAenean lectus. Pellentesque eget nunc. Donec quis orci eget orci vehicula condimentum.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 246330,
|
||||||
|
"test": {
|
||||||
|
"id": "Cross-platform needs-based firmware"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 340531,
|
||||||
|
"test": {
|
||||||
|
"id": "Total content-based data-warehouse"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 145457,
|
||||||
|
"test": {
|
||||||
|
"id": "Programmable transitional budgetary management"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13492,
|
||||||
|
"test": {
|
||||||
|
"id": "Switchable encompassing archive"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 310239,
|
||||||
|
"test": {
|
||||||
|
"id": "Self-enabling attitude-oriented strategy"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 20,
|
||||||
|
"content": "Morbi porttitor lorem id ligula. Suspendisse ornare consequat lectus. In est risus, auctor sed, tristique in, tempus sit amet, sem.\n\nFusce consequat. Nulla nisl. Nunc nisl.",
|
||||||
|
"comments": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 21,
|
||||||
|
"content": "Donec diam neque, vestibulum eget, vulputate ut, ultrices vel, augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec pharetra, magna vestibulum aliquet ultrices, erat tortor sollicitudin mi, sit amet lobortis sapien sapien non mi. Integer ac neque.\n\nDuis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.\n\nIn sagittis dui vel nisl. Duis ac nibh. Fusce lacus purus, aliquet at, feugiat non, pretium quis, lectus.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 909627,
|
||||||
|
"test": {
|
||||||
|
"id": "Expanded intangible forecast"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"username": "lwoodrooffe9",
|
||||||
|
"email": "mhowatt9@kickstarter.com",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"id": 31
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 44
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 38
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"profile": {
|
||||||
|
"id": 10,
|
||||||
|
"biography": "Nulla ut erat id mauris vulputate elementum. Nullam varius. Nulla facilisi.",
|
||||||
|
"website": "https://blinklist.com/semper/est/quam/pharetra/magna/ac.png?sagittis=eu&nam=tincidunt",
|
||||||
|
"profilePictureUrl": "http://dummyimage.com/121x100.png/5fa2dd/ffffff"
|
||||||
|
},
|
||||||
|
"posts": [
|
||||||
|
{
|
||||||
|
"id": 22,
|
||||||
|
"content": "Sed ante. Vivamus tortor. Duis mattis egestas metus.\n\nAenean fermentum. Donec ut mauris eget massa tempor convallis. Nulla neque libero, convallis eget, eleifend luctus, ultricies eu, nibh.\n\nQuisque id justo sit amet sapien dignissim vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla dapibus dolor vel est. Donec odio justo, sollicitudin ut, suscipit a, feugiat et, eros.",
|
||||||
|
"comments": [
|
||||||
|
{
|
||||||
|
"id": 831777,
|
||||||
|
"test": {
|
||||||
|
"id": "Open-source non-volatile help-desk"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 883941,
|
||||||
|
"test": {
|
||||||
|
"id": "Fully-configurable mission-critical emulation"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 759548,
|
||||||
|
"test": {
|
||||||
|
"id": "Right-sized bifurcated strategy"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 294894,
|
||||||
|
"test": {
|
||||||
|
"id": "Balanced explicit paradigm"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"id": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in New Issue