lab-3 in process

This commit is contained in:
Zakharov_Rostislav 2024-04-11 13:37:30 +04:00
parent 01d55b7611
commit 4dbd725780
20 changed files with 188 additions and 142 deletions

View File

@ -7,6 +7,17 @@ plugins {
group = 'com.ip'
version = '0.0.1-SNAPSHOT'
defaultTasks 'bootRun'
jar {
enabled = false
}
bootJar {
archiveFileName = String.format('%s-%s.jar', rootProject.name, version)
}
assert System.properties['java.specification.version'] == '17' || '21'
java {
sourceCompatibility = '17'
}
@ -17,10 +28,12 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
implementation 'org.modelmapper:modelmapper:3.2.0'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2:2.2.224'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

View File

@ -3,13 +3,15 @@ package com.ip.library.authors.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class AuthorDto {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
@NotBlank
@Size(min = 5, max = 20)
private String name;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId() {
return id;
}

View File

@ -4,15 +4,21 @@ import java.util.Objects;
import com.ip.library.core.model.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
@Entity
@Table(name = "authors")
public class AuthorEntity extends BaseEntity {
@Column(nullable = false, unique = true, length = 20)
private String name;
public AuthorEntity() {
super();
}
public AuthorEntity(Long id, String name) {
super(id);
public AuthorEntity(String name) {
this.name = name;
}

View File

@ -1,10 +1,11 @@
package com.ip.library.authors.repository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import com.ip.library.authors.model.AuthorEntity;
import com.ip.library.core.repository.MapRepository;
@Repository
public class AuthorRepository extends MapRepository<AuthorEntity> {
public interface AuthorRepository extends CrudRepository<AuthorEntity, Long> {
Optional<AuthorEntity> findByNameIgnoreCase(String name);
}

View File

@ -2,8 +2,10 @@ package com.ip.library.authors.service;
import java.util.List;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ip.library.core.error.NotFoundException;
import com.ip.library.authors.model.AuthorEntity;
@ -17,27 +19,49 @@ public class AuthorService {
this.repository = repository;
}
private void checkNameUniqueness(String name) {
if (repository.findByNameIgnoreCase(name).isPresent()) {
throw new IllegalArgumentException(
String.format("Author with name %s already exists", name)
);
}
}
@Transactional(readOnly = true)
public List<AuthorEntity> getAll() {
return repository.getAll();
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
}
@Transactional(readOnly = true)
public AuthorEntity get(Long id) {
return Optional.ofNullable(repository.get(id))
.orElseThrow(() -> new NotFoundException(id));
return repository.findById(id)
.orElseThrow(() -> new NotFoundException(AuthorEntity.class, id));
}
@Transactional
public AuthorEntity create(AuthorEntity entity) {
return repository.create(entity);
if (entity == null) {
throw new IllegalArgumentException("Creating AuthorEntity is null");
}
checkNameUniqueness(entity.getName());
return repository.save(entity);
}
@Transactional
public AuthorEntity update(Long id, AuthorEntity entity) {
if (entity == null) {
throw new IllegalArgumentException("Updating AuthorEntity is null");
}
final AuthorEntity existsEntity = get(id);
checkNameUniqueness(entity.getName());
existsEntity.setName(entity.getName());
return repository.update(existsEntity);
return repository.save(existsEntity);
}
@Transactional
public AuthorEntity delete(Long id) {
final AuthorEntity existsEntity = get(id);
return repository.delete(existsEntity);
repository.delete(existsEntity);
return existsEntity;
}
}

View File

@ -4,19 +4,32 @@ import java.util.Objects;
import com.ip.library.core.model.BaseEntity;
import com.ip.library.types.model.TypeEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import com.ip.library.authors.model.AuthorEntity;
@Entity
@Table(name = "books")
public class BookEntity extends BaseEntity {
@Column(nullable = false, unique = true, length = 50)
private String name;
@ManyToOne
@JoinColumn(name = "typeId", nullable = false)
private TypeEntity type;
@ManyToOne
@JoinColumn(name = "authorId", nullable = false)
private AuthorEntity author;
public BookEntity() {
super();
}
public BookEntity(Long id, String name, TypeEntity type, AuthorEntity author) {
super(id);
public BookEntity(String name, TypeEntity type, AuthorEntity author) {
this.name = name;
this.type = type;
this.author = author;

View File

@ -1,10 +1,15 @@
package com.ip.library.books.repository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import com.ip.library.books.model.BookEntity;
import com.ip.library.core.repository.MapRepository;
@Repository
public class BookRepository extends MapRepository<BookEntity> {
public interface BookRepository extends CrudRepository<BookEntity, Long> {
Optional<BookEntity> findByNameIgnoreCase(String name);
List<BookEntity> findByTypeId(long typeId);
List<BookEntity> findByAuthorId(long authorId);
List<BookEntity> findByTypeIdAndAuthorId(long typeId, long authorId);
}

View File

@ -3,8 +3,10 @@ package com.ip.library.books.service;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ip.library.books.model.BookEntity;
import com.ip.library.books.repository.BookRepository;
@ -18,34 +20,37 @@ public class BookService {
this.repository = repository;
}
@Transactional(readOnly = true)
public List<BookEntity> getAll(Long typeId, Long authorId) {
List<BookEntity> result = repository.getAll();
if (!Objects.equals(typeId, 0L)){
result = result.stream()
.filter(item -> item.getType().getId().equals(typeId))
.toList();
if (typeId <= 0L && authorId <= 0L) {
return StreamSupport.stream(repository.findAll().spliterator(), null).toList();
}
if (!Objects.equals(authorId, 0L)){
result = result.stream()
.filter(item -> item.getAuthor().getId().equals(authorId))
.toList();
if (typeId <= 0L){
return repository.findByAuthorId(authorId);
}
return result;
if (authorId <= 0L){
return repository.findByTypeId(typeId);
}
return repository.findByTypeIdAndAuthorId(typeId, authorId);
}
@Transactional(readOnly = true)
public List<BookEntity> getAll() {
return repository.getAll();
}
@Transactional(readOnly = true)
public BookEntity get(Long id) {
return Optional.ofNullable(repository.get(id))
.orElseThrow(() -> new NotFoundException(id));
}
@Transactional
public BookEntity create(BookEntity entity) {
return repository.create(entity);
}
@Transactional
public BookEntity update(Long id, BookEntity entity) {
final BookEntity existsEntity = get(id);
existsEntity.setName(entity.getName());
@ -54,6 +59,7 @@ public class BookService {
return repository.update(existsEntity);
}
@Transactional
public BookEntity delete(Long id) {
final BookEntity existsEntity = get(id);
return repository.delete(existsEntity);

View File

@ -1,6 +1,8 @@
package com.ip.library.core.configuration;
public class Constants {
public static final String SEQUENCE_NAME = "hibernate_sequence";
public static final String API_URL = "/api/1.0";
private Constants() {

View File

@ -1,7 +1,7 @@
package com.ip.library.core.error;
public class NotFoundException extends RuntimeException {
public NotFoundException(Long id) {
super(String.format("Entity with id [%s] is not found or not exists", id));
public <T> NotFoundException(Class<T> clazz, Long id) {
super(String.format("%s with id [%s] is not found or not exists", clazz.getSimpleName(), id));
}
}

View File

@ -1,15 +1,23 @@
package com.ip.library.core.model;
import com.ip.library.core.configuration.Constants;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.SequenceGenerator;
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = Constants.SEQUENCE_NAME)
@SequenceGenerator(name = Constants.SEQUENCE_NAME, sequenceName = Constants.SEQUENCE_NAME, allocationSize = 1)
protected Long id;
protected BaseEntity() {
}
protected BaseEntity(Long id) {
this.id = id;
}
public Long getId() {
return id;
}

View File

@ -1,17 +0,0 @@
package com.ip.library.core.repository;
import java.util.List;
public interface CommonRepository<E, T> {
List<E> getAll();
E get(T id);
E create(E entity);
E update(E entity);
E delete(E entity);
void deleteAll();
}

View File

@ -1,57 +0,0 @@
package com.ip.library.core.repository;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import com.ip.library.core.model.BaseEntity;
public abstract class MapRepository<E extends BaseEntity> implements CommonRepository<E, Long> {
private final Map<Long, E> entities = new TreeMap<>();
private Long lastId = 0L;
protected MapRepository() {
}
@Override
public List<E> getAll() {
return entities.values().stream().toList();
}
@Override
public E get(Long id) {
return entities.get(id);
}
@Override
public E create(E entity) {
lastId++;
entity.setId(lastId);
entities.put(lastId, entity);
return entity;
}
@Override
public E update(E entity) {
if (get(entity.getId()) == null) {
return null;
}
entities.put(entity.getId(), entity);
return entity;
}
@Override
public E delete(E entity) {
if (get(entity.getId()) == null) {
return null;
}
entities.remove(entity.getId());
return entity;
}
@Override
public void deleteAll() {
lastId = 0L;
entities.clear();
}
}

View File

@ -3,13 +3,15 @@ package com.ip.library.types.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class TypeDto {
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long id;
@NotBlank
@Size(min = 5, max = 20)
private String name;
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Long getId() {
return id;
}

View File

@ -4,15 +4,21 @@ import java.util.Objects;
import com.ip.library.core.model.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
@Entity
@Table(name = "types")
public class TypeEntity extends BaseEntity {
@Column(nullable = false, unique = true, length = 20)
private String name;
public TypeEntity() {
super();
}
public TypeEntity(Long id, String name) {
super(id);
public TypeEntity(String name) {
this.name = name;
}

View File

@ -1,10 +1,11 @@
package com.ip.library.types.repository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
import org.springframework.data.repository.CrudRepository;
import com.ip.library.core.repository.MapRepository;
import com.ip.library.types.model.TypeEntity;
@Repository
public class TypeRepository extends MapRepository<TypeEntity> {
public interface TypeRepository extends CrudRepository<TypeEntity, Long> {
Optional<TypeEntity> findByNameIgnoreCase(String name);
}

View File

@ -1,9 +1,10 @@
package com.ip.library.types.service;
import java.util.List;
import java.util.Optional;
import java.util.stream.StreamSupport;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ip.library.core.error.NotFoundException;
import com.ip.library.types.model.TypeEntity;
@ -17,27 +18,49 @@ public class TypeService {
this.repository = repository;
}
private void checkNameUniqueness(String name){
if (repository.findByNameIgnoreCase(name).isPresent()) {
throw new IllegalArgumentException(
String.format("Type with name %s already exists", name)
);
}
}
@Transactional(readOnly = true)
public List<TypeEntity> getAll() {
return repository.getAll();
return StreamSupport.stream(repository.findAll().spliterator(), false).toList();
}
public TypeEntity get(Long id) {
return Optional.ofNullable(repository.get(id))
.orElseThrow(() -> new NotFoundException(id));
@Transactional(readOnly = true)
public TypeEntity get(long id) {
return repository.findById(id)
.orElseThrow(() -> new NotFoundException(TypeEntity.class, id));
}
@Transactional
public TypeEntity create(TypeEntity entity) {
return repository.create(entity);
if (entity == null) {
throw new IllegalArgumentException("Creating TypeEntity is null");
}
checkNameUniqueness(entity.getName());
return repository.save(entity);
}
@Transactional
public TypeEntity update(Long id, TypeEntity entity) {
if (entity == null) {
throw new IllegalArgumentException("Updating TypeEntity is null");
}
final TypeEntity existsEntity = get(id);
checkNameUniqueness(entity.getName());
existsEntity.setName(entity.getName());
return repository.update(existsEntity);
return repository.save(existsEntity);
}
@Transactional
public TypeEntity delete(Long id) {
final TypeEntity existsEntity = get(id);
return repository.delete(existsEntity);
repository.delete(existsEntity);
return existsEntity;
}
}

View File

@ -6,9 +6,18 @@ import java.util.Objects;
import com.ip.library.books.model.BookEntity;
import com.ip.library.core.model.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
@Entity
@Table(name = "users")
public class UserEntity extends BaseEntity {
private String name;
@Column(nullable = false, unique = true, length = 20)
private String login;
@Column(nullable = false, unique = true, length = 20)
private String password;
@Column(nullable = false, unique = true, length = 20)
private String role;
private List<BookEntity> books;
@ -16,20 +25,19 @@ public class UserEntity extends BaseEntity {
super();
}
public UserEntity(Long id, String name, String password, String role, List<BookEntity> books) {
super(id);
this.name = name;
public UserEntity(String name, String password, String role, List<BookEntity> books) {
this.login = name;
this.password = password;
this.role = role;
this.books = books;
}
public String getName() {
return name;
public String getLogin() {
return login;
}
public void setName(String name) {
this.name = name;
public void setLogin(String name) {
this.login = name;
}
public String getPassword() {
@ -58,7 +66,7 @@ public class UserEntity extends BaseEntity {
@Override
public int hashCode() {
return Objects.hash(id, name, password, role);
return Objects.hash(id, login, password, role);
}
@Override
@ -69,7 +77,7 @@ public class UserEntity extends BaseEntity {
return false;
final UserEntity other = (UserEntity) obj;
return Objects.equals(other.getId(), id)
&& Objects.equals(other.getName(), name)
&& Objects.equals(other.getLogin(), login)
&& Objects.equals(other.getPassword(), password)
&& Objects.equals(other.getRole(), role)
&& Objects.equals(other.getBooks(), books);

View File

@ -39,7 +39,7 @@ public class UserService {
public UserEntity update(Long id, UserEntity entity) {
final UserEntity existsEntity = get(id);
existsEntity.setName(entity.getName());
existsEntity.setLogin(entity.getLogin());
return repository.update(existsEntity);
}

View File

@ -57,7 +57,7 @@ class UsersTests {
@Test
void createTest() {
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertEquals("user3", user.getName());
Assertions.assertEquals("user3", user.getLogin());
Assertions.assertEquals("aqw2sed45", user.getPassword());
Assertions.assertEquals("user", user.getRole());
Assertions.assertEquals(0, user.getBooks().size());
@ -76,7 +76,7 @@ class UsersTests {
if (user.getId() != 1L)
testId = 1L;
else testId = 2L;
final String testName = user.getName() + "TEST";
final String testName = user.getLogin() + "TEST";
final String testPassword = user.getPassword() + "TEST";
final String testRole = "admin";
List<BookEntity> testBooks = new ArrayList<BookEntity>();
@ -85,7 +85,7 @@ class UsersTests {
testPassword, testRole, testBooks));
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertNotEquals(testId, user.getId());
Assertions.assertEquals(testName, user.getName());
Assertions.assertEquals(testName, user.getLogin());
Assertions.assertNotEquals(testPassword, user.getPassword());
Assertions.assertNotEquals(testRole, user.getRole());
Assertions.assertEquals(0, user.getBooks().size());
@ -96,7 +96,7 @@ class UsersTests {
userService.delete(user.getId());
Assertions.assertEquals(2, userService.getAll().size());
final UserEntity newEntity = userService.create(new UserEntity(null,
user.getName(), user.getPassword(), null, null));
user.getLogin(), user.getPassword(), null, null));
Assertions.assertEquals(3, userService.getAll().size());
Assertions.assertNotEquals(user.getId(), newEntity.getId());
}