Skip to content

Commit

Permalink
spring data projections
Browse files Browse the repository at this point in the history
  • Loading branch information
myluckagain committed Mar 20, 2021
1 parent 6c6b299 commit d5982ea
Show file tree
Hide file tree
Showing 14 changed files with 320 additions and 0 deletions.
62 changes: 62 additions & 0 deletions spring-data-projection/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.sysout</groupId>
<artifactId>spring-data-projections</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-data-projections</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>


<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package ru.sysout.projections;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {


public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.sysout.projections.dao;


import org.springframework.data.jpa.repository.JpaRepository;
import ru.sysout.projections.dto.PostView;
import ru.sysout.projections.model.Post;

import java.util.List;

public interface PostRepository extends JpaRepository<Post, Long> {

List<PostView> findByTitle(String title);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ru.sysout.projections.dao;


import org.springframework.data.jpa.repository.JpaRepository;
import ru.sysout.projections.dto.UserDto;
import ru.sysout.projections.dto.UserView;
import ru.sysout.projections.model.User;

import java.util.List;

public interface UserRepository extends JpaRepository<User, Long> {

UserView findByNickname(String nickname);

List<UserDto> findByEmail(String email);

<T> T findByNickname(String nickname, Class<T> type);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.sysout.projections.dto;

public interface PostView {

long getId();
String getTitle();
UserView getUser();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.sysout.projections.dto;


import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class UserDto {
private Long id;
private String nickname;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.sysout.projections.dto;


import org.springframework.beans.factory.annotation.Value;

public interface UserView {

String getNickname();

@Value("#{target.email + ' ' + target.password}")
String getInfo();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ru.sysout.projections.model;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import java.time.LocalDateTime;

@Entity
@Data
@NoArgsConstructor
public class Post {
@Id
@GeneratedValue(generator = "sequence")
private Long id;

private String title;

private String text;

@CreationTimestamp
private LocalDateTime createdDateTime;

@ManyToOne
private User user;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ru.sysout.projections.model;


import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Data
@Entity
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(generator = "sequence")
private Long id;

private String email;

private String nickname;


private String password;

private String role="ROLE_USER";

private boolean locked=false;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
8 changes: 8 additions & 0 deletions spring-data-projection/src/main/resources/data.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
insert into user (id, email, nickname, password, role, locked) values (1,'admin@example.com', 'admin', 'password', 'ROLE_ADMIN', false);
insert into user (id, email, nickname, password, role, locked) values (2,'user@example.com', 'bob', 'password', 'ROLE_USER', false);

insert into post (id, title, text, created_date_time, user_id) values (3,'Super Post3', 'Super Text3', CURRENT_TIMESTAMP(), 1);
insert into post (id, title, text, created_date_time, user_id) values (4,'Super Post4', 'Super Text4', CURRENT_TIMESTAMP(), 1);
insert into post (id, title, text, created_date_time, user_id) values (5,'Super Post5', 'Super Text5', CURRENT_TIMESTAMP(), 1);


31 changes: 31 additions & 0 deletions spring-data-projection/src/main/resources/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
CREATE TABLE IF NOT EXISTS USER (
id integer not null,
email varchar(255) not null,
nickname varchar(255) not null,
password varchar(255) not null,
role varchar(255) not null,
locked boolean,
primary key (id)
);
ALTER TABLE
USER
ADD CONSTRAINT EMAIL_UNIQUE
UNIQUE (email);
ALTER TABLE
USER
ADD CONSTRAINT NICKNAME_UNIQUE
UNIQUE (nickname);


CREATE TABLE IF NOT EXISTS POST (
id integer not null,
title varchar(255),
text clob,
created_date_time timestamp,
user_id integer not null,
primary key (id)
);
ALTER TABLE POST
ADD FOREIGN KEY (user_id) REFERENCES USER(id);

create sequence hiber_sequence MINVALUE 10;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.sysout.projections.dao;


import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import ru.sysout.projections.dto.PostView;

import java.util.List;
import java.util.stream.Collectors;

import static org.junit.jupiter.api.Assertions.assertLinesMatch;

@SpringBootTest
public class PostRepositoryTest {
@Autowired
private PostRepository postRepository;

@Test
public void shouldFindInterfaceProjection() {
List<PostView> list = postRepository.findByTitle("Super Post3");

List expected = List.of("Super Post3");

List actual = list.stream().map(el -> el.getTitle()).collect(Collectors.toList());

assertLinesMatch(expected, actual);

}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ru.sysout.projections.dao;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import ru.sysout.projections.dto.UserDto;
import ru.sysout.projections.dto.UserView;
import ru.sysout.projections.model.User;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;

@Test
public void shouldFindOpenProjection() {
UserView userView = userRepository.findByNickname("admin");

assertEquals("admin@example.com password", userView.getInfo());
}

@Test
public void shouldFindClassProjection() {
List<UserDto> userDtos = userRepository.findByEmail("admin@example.com");
UserDto userDto = userDtos.get(0);
assertEquals("admin", userDto.getNickname());
}

@Test
public void shouldFindDynamicProjection() {
UserDto userDto = userRepository.findByNickname("admin", UserDto.class);
assertEquals("admin", userDto.getNickname());

User user = userRepository.findByNickname("admin", User.class);
assertEquals("admin", user.getNickname());

UserView userView = userRepository.findByNickname("admin", UserView.class);
assertEquals("admin", userView.getNickname());
}
}

0 comments on commit d5982ea

Please sign in to comment.