diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c5f3f6b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} \ No newline at end of file diff --git a/lab2/build.gradle b/lab2/build.gradle index b7867b9..4a29ef4 100644 --- a/lab2/build.gradle +++ b/lab2/build.gradle @@ -1,12 +1,23 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.2.3' + id 'org.springframework.boot' version '3.2.4' id 'io.spring.dependency-management' version '1.1.4' } group = 'com.example' 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,12 +28,16 @@ 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' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'com.h2database:h2:2.2.224' + testImplementation 'org.springframework.boot:spring-boot-starter-test' } tasks.named('test') { useJUnitPlatform() -} +} \ No newline at end of file diff --git a/lab2/src/main/java/com/example/demo/DemoApplication.java b/lab2/src/main/java/com/example/demo/DemoApplication.java index ec7bb60..0e2c36e 100644 --- a/lab2/src/main/java/com/example/demo/DemoApplication.java +++ b/lab2/src/main/java/com/example/demo/DemoApplication.java @@ -11,12 +11,13 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import com.example.demo.comment.model.CommentEntity; -import com.example.demo.comment.service.CommentService; +import com.example.demo.comments.model.CommentEntity; +import com.example.demo.comments.service.CommentService; import com.example.demo.news.model.NewEntity; import com.example.demo.news.service.NewService; -import com.example.demo.tage.model.TageEntity; -import com.example.demo.tage.service.TageService; +import com.example.demo.newtage.model.NewTageEntity; +import com.example.demo.tages.model.TageEntity; +import com.example.demo.tages.service.TageService; import com.example.demo.users.model.UserEntity; import com.example.demo.users.service.UserService; @@ -52,11 +53,13 @@ public class DemoApplication implements CommandLineRunner { final var tage4 = tageService.create(new TageEntity(null, "программирование")); // new - final NewEntity new1 = newService.create(new NewEntity(null, "Чемпионат ICPC", new Date(), Arrays.asList(tage1, tage2), + final NewEntity new1 = newService.create(new NewEntity(null, "Чемпионат ICPC", new Date(), "Студенты выступят на Чемпионате мира по программированию в Северной Евразии.")); - final NewEntity new2 = newService.create(new NewEntity(null, "Новый год 2024", new Date(2024 - 1 - 01), Arrays.asList(tage3, tage4), + final NewEntity new2 = newService.create(new NewEntity(null, "Новый год 2024", new Date(2024 - 1 - 01), "Администрация ulstu поздравляет студентов и преподавателей с Новым годом и желает крепкого здоровья и успешного Года Дракона!")); - + + final NewTageEntity newTage1 = new NewTageEntity(new1, tage1); + new1.addTage(newTage1); // user final var user1 = userService.create(new UserEntity(null, "beko", "111", "ddwwdd", diff --git a/lab2/src/main/java/com/example/demo/comment/repository/CommentRepository.java b/lab2/src/main/java/com/example/demo/comment/repository/CommentRepository.java deleted file mode 100644 index dd09b57..0000000 --- a/lab2/src/main/java/com/example/demo/comment/repository/CommentRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.demo.comment.repository; - -import org.springframework.stereotype.Repository; - -import com.example.demo.comment.model.CommentEntity; -import com.example.demo.core.repository.MapRepository; - -@Repository -public class CommentRepository extends MapRepository { -} diff --git a/lab2/src/main/java/com/example/demo/comment/service/CommentService.java b/lab2/src/main/java/com/example/demo/comment/service/CommentService.java deleted file mode 100644 index 8e93ae2..0000000 --- a/lab2/src/main/java/com/example/demo/comment/service/CommentService.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.example.demo.comment.service; - -import java.util.List; -import java.util.Objects; -import java.util.Optional; - -import org.springframework.stereotype.Service; - -import com.example.demo.core.error.NotFoundException; -import com.example.demo.comment.model.CommentEntity; -import com.example.demo.comment.repository.CommentRepository; - -@Service -public class CommentService { - private final CommentRepository repository; - - public CommentService(CommentRepository repository) { - this.repository = repository; - } - - public List getAll(Long newId) { - if (Objects.equals(newId, 0L)) { - return repository.getAll(); - } - return repository.getAll().stream() - .filter(item -> item.getNew().getId().equals(newId)) - .toList(); - } - - public CommentEntity get(Long id) { - return Optional.ofNullable(repository.get(id)) - .orElseThrow(() -> new NotFoundException(id)); - } - - public CommentEntity create(CommentEntity entity) { - return repository.create(entity); - } - - public CommentEntity update(Long id, CommentEntity entity) { - final CommentEntity existsEntity = get(id); - existsEntity.setDate(entity.getDate()); - existsEntity.setText(entity.getText()); - return repository.update(existsEntity); - } - - public CommentEntity delete(Long id) { - final CommentEntity existsEntity = get(id); - return repository.delete(existsEntity); - } -} diff --git a/lab2/src/main/java/com/example/demo/comment/api/CommentController.java b/lab2/src/main/java/com/example/demo/comments/api/CommentController.java similarity index 94% rename from lab2/src/main/java/com/example/demo/comment/api/CommentController.java rename to lab2/src/main/java/com/example/demo/comments/api/CommentController.java index a5617de..6a2747e 100644 --- a/lab2/src/main/java/com/example/demo/comment/api/CommentController.java +++ b/lab2/src/main/java/com/example/demo/comments/api/CommentController.java @@ -1,4 +1,4 @@ -package com.example.demo.comment.api; +package com.example.demo.comments.api; import java.util.List; @@ -13,10 +13,10 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.example.demo.comments.model.CommentEntity; +import com.example.demo.comments.service.CommentService; import com.example.demo.core.configuration.Constants; import com.example.demo.news.service.NewService; -import com.example.demo.comment.model.CommentEntity; -import com.example.demo.comment.service.CommentService; import jakarta.validation.Valid; diff --git a/lab2/src/main/java/com/example/demo/comment/api/CommentDto.java b/lab2/src/main/java/com/example/demo/comments/api/CommentDto.java similarity index 90% rename from lab2/src/main/java/com/example/demo/comment/api/CommentDto.java rename to lab2/src/main/java/com/example/demo/comments/api/CommentDto.java index fbcb0c7..837c172 100644 --- a/lab2/src/main/java/com/example/demo/comment/api/CommentDto.java +++ b/lab2/src/main/java/com/example/demo/comments/api/CommentDto.java @@ -1,9 +1,7 @@ -package com.example.demo.comment.api; +package com.example.demo.comments.api; import java.util.Date; -import com.example.demo.news.model.NewEntity; -import com.example.demo.users.model.UserEntity; import com.fasterxml.jackson.annotation.JsonProperty; import jakarta.validation.constraints.Min; diff --git a/lab2/src/main/java/com/example/demo/comment/model/CommentEntity.java b/lab2/src/main/java/com/example/demo/comments/model/CommentEntity.java similarity index 72% rename from lab2/src/main/java/com/example/demo/comment/model/CommentEntity.java rename to lab2/src/main/java/com/example/demo/comments/model/CommentEntity.java index c452580..645d27d 100644 --- a/lab2/src/main/java/com/example/demo/comment/model/CommentEntity.java +++ b/lab2/src/main/java/com/example/demo/comments/model/CommentEntity.java @@ -1,4 +1,4 @@ -package com.example.demo.comment.model; +package com.example.demo.comments.model; import java.util.Date; import java.util.Objects; @@ -7,10 +7,24 @@ import com.example.demo.core.model.BaseEntity; import com.example.demo.news.model.NewEntity; import com.example.demo.users.model.UserEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; + +@Entity +@Table(name = "comments") public class CommentEntity extends BaseEntity { + @Column(nullable = false) private Date date; + @Column(nullable = false, length = 200) private String text; + @ManyToOne + @JoinColumn(name = "newsId", nullable = false) private NewEntity news; + @ManyToOne + @JoinColumn(name = "userId", nullable = false) private UserEntity user; public CommentEntity() { @@ -43,6 +57,9 @@ public class CommentEntity extends BaseEntity { public void setNew(NewEntity news) { this.news = news; + if (!news.getComments().contains(this)) { + news.getComments().add(this); + } } public NewEntity getNew() { @@ -51,6 +68,9 @@ public class CommentEntity extends BaseEntity { public void setUser(UserEntity user) { this.user = user; + if (!user.getComments().contains(this)) { + user.getComments().add(this); + } } public UserEntity getUser() { diff --git a/lab2/src/main/java/com/example/demo/comments/repository/CommentRepository.java b/lab2/src/main/java/com/example/demo/comments/repository/CommentRepository.java new file mode 100644 index 0000000..e2b11e7 --- /dev/null +++ b/lab2/src/main/java/com/example/demo/comments/repository/CommentRepository.java @@ -0,0 +1,8 @@ +package com.example.demo.comments.repository; + +import org.springframework.data.repository.CrudRepository; + +import com.example.demo.comments.model.CommentEntity; + +public interface CommentRepository extends CrudRepository { +} diff --git a/lab2/src/main/java/com/example/demo/comments/service/CommentService.java b/lab2/src/main/java/com/example/demo/comments/service/CommentService.java new file mode 100644 index 0000000..8523b22 --- /dev/null +++ b/lab2/src/main/java/com/example/demo/comments/service/CommentService.java @@ -0,0 +1,60 @@ +package com.example.demo.comments.service; + +import java.util.List; +import java.util.Objects; +import java.util.stream.StreamSupport; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.example.demo.comments.model.CommentEntity; +import com.example.demo.comments.repository.CommentRepository; +import com.example.demo.core.error.NotFoundException; + +@Service +public class CommentService { + private final CommentRepository repository; + + public CommentService(CommentRepository repository) { + this.repository = repository; + } + + @Transactional(readOnly = true) + public List getAll(Long newId) { + if (Objects.equals(newId, 0L)) { + return StreamSupport.stream(repository.findAll().spliterator(), false).toList(); + } + return StreamSupport.stream(repository.findAll().spliterator(), false) + .filter(item -> item.getNew().getId().equals(newId)) + .toList(); + } + + @Transactional(readOnly = true) + public CommentEntity get(Long id) { + return repository.findById(id) + .orElseThrow(() -> new NotFoundException(CommentEntity.class, id)); + } + + @Transactional + public CommentEntity create(CommentEntity entity) { + if (entity == null) { + throw new IllegalArgumentException("Entity is null"); + } + return repository.save(entity); + } + + @Transactional + public CommentEntity update(Long id, CommentEntity entity) { + final CommentEntity existsEntity = get(id); + existsEntity.setDate(entity.getDate()); + existsEntity.setText(entity.getText()); + return repository.save(entity); + } + + @Transactional + public CommentEntity delete(Long id) { + final CommentEntity existsEntity = get(id); + repository.delete(existsEntity); + return existsEntity; + } +} diff --git a/lab2/src/main/java/com/example/demo/core/error/NotFoundException.java b/lab2/src/main/java/com/example/demo/core/error/NotFoundException.java index 586af3c..a61d118 100644 --- a/lab2/src/main/java/com/example/demo/core/error/NotFoundException.java +++ b/lab2/src/main/java/com/example/demo/core/error/NotFoundException.java @@ -1,7 +1,7 @@ package com.example.demo.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 NotFoundException(Class clazz, Long id) { + super(String.format("%s with id [%s] is not found or not exists", clazz.getSimpleName(), id)); } } diff --git a/lab2/src/main/java/com/example/demo/news/api/NewController.java b/lab2/src/main/java/com/example/demo/news/api/NewController.java index dac914d..6006f83 100644 --- a/lab2/src/main/java/com/example/demo/news/api/NewController.java +++ b/lab2/src/main/java/com/example/demo/news/api/NewController.java @@ -18,8 +18,9 @@ import org.springframework.web.bind.annotation.RestController; import com.example.demo.core.configuration.Constants; import com.example.demo.news.model.NewEntity; import com.example.demo.news.service.NewService; -import com.example.demo.tage.model.TageEntity; -import com.example.demo.tage.service.TageService; +import com.example.demo.tages.api.TageDto; +import com.example.demo.tages.model.TageEntity; +import com.example.demo.tages.service.TageService; import jakarta.validation.Valid; @@ -27,29 +28,23 @@ import jakarta.validation.Valid; @RequestMapping(Constants.API_URL + "/new") public class NewController { private final NewService newService; - private final TageService tageService; private final ModelMapper modelMapper; - public NewController(NewService newService, TageService tageService, ModelMapper modelMapper) { + public NewController(NewService newService, ModelMapper modelMapper) { this.newService = newService; this.modelMapper = modelMapper; - this.tageService = tageService; } private NewDto toDto(NewEntity entity) { return modelMapper.map(entity, NewDto.class); } + private NewDto toTageDto(TageEntity entity) { + return modelMapper.map(entity, NewDto.class); + } + private NewEntity toEntity(NewDto dto) { - final var entity = modelMapper.map(dto, NewEntity.class); - List tagesId = dto.getTagesId(); - List tages = Arrays.asList(); - for (var tageId : tagesId) - { - tages.add(tageService.get(tageId)); - } - entity.setTage(tages); - return entity; + return modelMapper.map(dto, NewEntity.class); } @GetMapping @@ -68,7 +63,7 @@ public class NewController { } @PutMapping("/{id}") - public NewDto update(@PathVariable(name = "id") Long id, @RequestBody NewDto dto) { + public NewDto update(@PathVariable(name = "id") Long id, @RequestBody @Valid NewDto dto) { return toDto(newService.update(id, toEntity(dto))); } @@ -76,4 +71,36 @@ public class NewController { public NewDto delete(@PathVariable(name = "id") Long id) { return toDto(newService.delete(id)); } + + @GetMapping("/{id}/tage") + public List getNewTages(@PathVariable(name = "id") Long id) { + return newService.getNewTages(id).stream() + .map(this::toTageDto) + .toList(); + } + + @PostMapping("/{id}/tage") + public List enableNewTages( + @PathVariable(name = "id") Long id, + @RequestParam(name = "tages", defaultValue = "") List tagesIds) { + return newService.enableNewTages(id, tagesIds).stream() + .map(this::toTageDto) + .toList(); + } + + @DeleteMapping("/{id}/tage") + public List disableNewTages( + @PathVariable(name = "id") Long id, + @RequestParam(name = "tages", defaultValue = "") List tagesIds) { + return newService.disableNewTages(id, tagesIds).stream() + .map(this::toTageDto) + .toList(); + } + + @DeleteMapping("/{id}/tage/all") + public List deleteAllNewTages(@PathVariable(name = "id") Long id) { + return newService.deleteAllNewTages(id).stream() + .map(this::toTageDto) + .toList(); + } } diff --git a/lab2/src/main/java/com/example/demo/news/model/NewEntity.java b/lab2/src/main/java/com/example/demo/news/model/NewEntity.java index ae53cd7..640c845 100644 --- a/lab2/src/main/java/com/example/demo/news/model/NewEntity.java +++ b/lab2/src/main/java/com/example/demo/news/model/NewEntity.java @@ -1,27 +1,45 @@ package com.example.demo.news.model; import java.util.Date; -import java.util.List; +import java.util.HashSet; import java.util.Objects; +import java.util.Set; +import com.example.demo.comments.model.CommentEntity; import com.example.demo.core.model.BaseEntity; -import com.example.demo.tage.model.TageEntity; +import com.example.demo.newtage.model.NewTageEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OrderBy; +import jakarta.persistence.Table; + +@Entity +@Table(name = "news") public class NewEntity extends BaseEntity { + @Column(nullable = false, length = 50) private String title; + @Column(nullable = false) private Date date; - private List tages; + @Column(nullable = false, length = 150) private String text; + @OneToMany(mappedBy = "new", cascade = CascadeType.ALL) + @OrderBy("id ASC") + private Set newTages = new HashSet<>(); + @OneToMany(mappedBy = "new", cascade = CascadeType.ALL) + @OrderBy("id ASC") + private Set comments = new HashSet<>(); public NewEntity() { super(); } - public NewEntity(Long id, String title, Date date, List tages, String text) { + public NewEntity(Long id, String title, Date date, String text) { super(id); this.title = title; this.date = date; - this.tages = tages; this.text = text; } @@ -41,14 +59,6 @@ public class NewEntity extends BaseEntity { this.date = date; } - public List getTage() { - return tages; - } - - public void setTage(List tages) { - this.tages = tages; - } - public String getText() { return text; } @@ -57,9 +67,31 @@ public class NewEntity extends BaseEntity { this.text = text; } + public Set getNewTages() { + return newTages; + } + + public void addTage(NewTageEntity newTage) { + if (newTage.getNew() != this) { + newTage.setNew(this); + } + newTages.add(newTage); + } + + public void deleteTage(NewTageEntity newTage) { + if (newTage.getNew() != this) { + return; + } + newTages.remove(newTage); + } + + public Set getComments() { + return comments; + } + @Override public int hashCode() { - return Objects.hash(id, title, date, tages, text); + return Objects.hash(id, title, date, newTages, text); } @Override @@ -72,7 +104,7 @@ public class NewEntity extends BaseEntity { return Objects.equals(other.getId(), id) && Objects.equals(other.getTitle(), title) && Objects.equals(other.getDate(), date) - && Objects.equals(other.getTage(), tages) + && Objects.equals(other.getNewTages(), newTages) && Objects.equals(other.getText(), text); } } diff --git a/lab2/src/main/java/com/example/demo/news/repository/NewRepository.java b/lab2/src/main/java/com/example/demo/news/repository/NewRepository.java index 448d25a..287435a 100644 --- a/lab2/src/main/java/com/example/demo/news/repository/NewRepository.java +++ b/lab2/src/main/java/com/example/demo/news/repository/NewRepository.java @@ -1,10 +1,8 @@ package com.example.demo.news.repository; -import org.springframework.stereotype.Repository; +import org.springframework.data.repository.CrudRepository; -import com.example.demo.core.repository.MapRepository; import com.example.demo.news.model.NewEntity; -@Repository -public class NewRepository extends MapRepository { +public interface NewRepository extends CrudRepository { } diff --git a/lab2/src/main/java/com/example/demo/news/service/NewService.java b/lab2/src/main/java/com/example/demo/news/service/NewService.java index 3d831fa..ed5f75d 100644 --- a/lab2/src/main/java/com/example/demo/news/service/NewService.java +++ b/lab2/src/main/java/com/example/demo/news/service/NewService.java @@ -1,46 +1,87 @@ package com.example.demo.news.service; import java.util.List; -import java.util.Optional; +import java.util.Objects; +import java.util.stream.StreamSupport; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import com.example.demo.core.error.NotFoundException; import com.example.demo.news.model.NewEntity; import com.example.demo.news.repository.NewRepository; +import com.example.demo.newtage.model.NewTageEntity; +import com.example.demo.tages.model.TageEntity; +import com.example.demo.tages.service.TageService; @Service public class NewService { private final NewRepository repository; + private final TageService tageService; - public NewService(NewRepository repository) { + public NewService(NewRepository repository, TageService tageService) { this.repository = repository; + this.tageService = tageService; } + @Transactional(readOnly = true) public List getAll() { - return repository.getAll(); + return StreamSupport.stream(repository.findAll().spliterator(), false).toList(); } + @Transactional(readOnly = true) public NewEntity get(Long id) { - return Optional.ofNullable(repository.get(id)) - .orElseThrow(() -> new NotFoundException(id)); + return repository.findById(id) + .orElseThrow(() -> new NotFoundException(NewEntity.class, id)); } + @Transactional public NewEntity create(NewEntity entity) { - return repository.create(entity); + if (entity == null) { + throw new IllegalArgumentException("Entity is null"); + } + repository.save(entity); + tageService.getAll().forEach(tage -> { + final NewTageEntity userTage = new NewTageEntity(entity, tage); + userTage.setNew(entity); + userTage.setTage(tage); + }); + return repository.save(entity); } + @Transactional public NewEntity update(Long id, NewEntity entity) { final NewEntity existsEntity = get(id); existsEntity.setTitle(entity.getTitle()); existsEntity.setDate(entity.getDate()); - existsEntity.setTage(entity.getTage()); existsEntity.setText(entity.getText()); - return repository.update(existsEntity); + return repository.save(existsEntity); } + @Transactional public NewEntity delete(Long id) { final NewEntity existsEntity = get(id); - return repository.delete(existsEntity); + repository.delete(existsEntity); + return existsEntity; + } + + @Transactional(readOnly = true) + public List getNewTages(long id) { + return get(id).getNewTages().stream() + .map(NewTageEntity::getTage) + .toList(); + } + + @Transactional + public List deleteAllNewTages(long id) { + final NewEntity existsNew = get(id); + final List tages = existsNew.getNewTages().stream() + .filter(tage -> Objects.nonNull(tage.getTage())) + .toList(); + tages.forEach(existsNew::deleteTage); + repository.save(existsNew); + return tages.stream() + .map(NewTageEntity::getTage) + .toList(); } } diff --git a/lab2/src/main/java/com/example/demo/newtage/model/NewTageEntity.java b/lab2/src/main/java/com/example/demo/newtage/model/NewTageEntity.java new file mode 100644 index 0000000..3bc0e33 --- /dev/null +++ b/lab2/src/main/java/com/example/demo/newtage/model/NewTageEntity.java @@ -0,0 +1,84 @@ +package com.example.demo.newtage.model; + +import java.util.Objects; + +import com.example.demo.news.model.NewEntity; +import com.example.demo.tages.model.TageEntity; + +import jakarta.persistence.EmbeddedId; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.MapsId; +import jakarta.persistence.Table; + +@Entity +@Table(name = "news_tages") +public class NewTageEntity { + @EmbeddedId + private NewTageId id = new NewTageId(); + + @ManyToOne + @MapsId("newId") + @JoinColumn(name = "new_id") + private NewEntity news; + @ManyToOne + @MapsId("tageId") + @JoinColumn(name = "tage_id") + private TageEntity tage; + + public NewTageEntity() {} + + public NewTageEntity(NewEntity news, TageEntity tage) { + this.news = news; + this.tage = tage; + } + + public NewTageId getId() { + return id; + } + + public void setId(NewTageId id) { + this.id = id; + } + + public NewEntity getNew() { + return news; + } + + public void setNew(NewEntity news) { + this.news = news; + if (!news.getNewTages().contains(this)) { + news.getNewTages().add(this); + } + } + + public TageEntity getTage() { + return tage; + } + + public void setTage(TageEntity tage) { + this.tage = tage; + if (!tage.getNewTages().contains(this)) { + tage.getNewTages().add(this); + } + } + + @Override + public int hashCode() { + return Objects.hash(id, news.getId(), tage.getId()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + NewTageEntity other = (NewTageEntity) obj; + return Objects.equals(id, other.id) + && Objects.equals(news.getId(), other.news.getId()) + && Objects.equals(tage.getId(), other.tage.getId()); + } + +} diff --git a/lab2/src/main/java/com/example/demo/newtage/model/NewTageId.java b/lab2/src/main/java/com/example/demo/newtage/model/NewTageId.java new file mode 100644 index 0000000..627659c --- /dev/null +++ b/lab2/src/main/java/com/example/demo/newtage/model/NewTageId.java @@ -0,0 +1,53 @@ +package com.example.demo.newtage.model; + +import java.util.Objects; +import java.util.Optional; + +import jakarta.persistence.Embeddable; + +@Embeddable +public class NewTageId { + private Long newId; + private Long tageId; + + public NewTageId() {} + + public NewTageId(Long newId, Long tageId) { + this.newId = newId; + this.tageId = tageId; + } + + public Long getNewId() { + return newId; + } + + public void setNewId(Long newId) { + this.newId = newId; + } + + public Long getTageId() { + return tageId; + } + + public void setTageId(Long tageId) { + this.tageId = tageId; + } + + @Override + public int hashCode() { + return Objects.hash( + Optional.ofNullable(newId).orElse(0L), + Optional.ofNullable(tageId).orElse(0L)); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + NewTageId other = (NewTageId) obj; + return Objects.equals(newId, other.newId) + && Objects.equals(tageId, other.tageId); + } +} diff --git a/lab2/src/main/java/com/example/demo/tage/repository/TageRepository.java b/lab2/src/main/java/com/example/demo/tage/repository/TageRepository.java deleted file mode 100644 index 3dad637..0000000 --- a/lab2/src/main/java/com/example/demo/tage/repository/TageRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.demo.tage.repository; - -import org.springframework.stereotype.Repository; - -import com.example.demo.core.repository.MapRepository; -import com.example.demo.tage.model.TageEntity; - -@Repository -public class TageRepository extends MapRepository { -} diff --git a/lab2/src/main/java/com/example/demo/tage/service/TageService.java b/lab2/src/main/java/com/example/demo/tage/service/TageService.java deleted file mode 100644 index ce24920..0000000 --- a/lab2/src/main/java/com/example/demo/tage/service/TageService.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.example.demo.tage.service; - -import java.util.List; -import java.util.Optional; - -import org.springframework.stereotype.Service; - -import com.example.demo.core.error.NotFoundException; -import com.example.demo.tage.model.TageEntity; -import com.example.demo.tage.repository.TageRepository; - -@Service -public class TageService { - private final TageRepository repository; - - public TageService(TageRepository repository) { - this.repository = repository; - } - - public List getAll() { - return repository.getAll(); - } - - public TageEntity get(Long id) { - return Optional.ofNullable(repository.get(id)) - .orElseThrow(() -> new NotFoundException(id)); - } - - public TageEntity create(TageEntity entity) { - return repository.create(entity); - } - - public TageEntity update(Long id, TageEntity entity) { - final TageEntity existsEntity = get(id); - existsEntity.setText(entity.getText()); - return repository.update(existsEntity); - } - - public TageEntity delete(Long id) { - final TageEntity existsEntity = get(id); - return repository.delete(existsEntity); - } -} diff --git a/lab2/src/main/java/com/example/demo/tage/api/TageController.java b/lab2/src/main/java/com/example/demo/tages/api/TageController.java similarity index 93% rename from lab2/src/main/java/com/example/demo/tage/api/TageController.java rename to lab2/src/main/java/com/example/demo/tages/api/TageController.java index 59b861f..4e62714 100644 --- a/lab2/src/main/java/com/example/demo/tage/api/TageController.java +++ b/lab2/src/main/java/com/example/demo/tages/api/TageController.java @@ -1,4 +1,4 @@ -package com.example.demo.tage.api; +package com.example.demo.tages.api; import java.util.List; @@ -13,8 +13,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.example.demo.core.configuration.Constants; -import com.example.demo.tage.model.TageEntity; -import com.example.demo.tage.service.TageService; +import com.example.demo.tages.model.TageEntity; +import com.example.demo.tages.service.TageService; import jakarta.validation.Valid; diff --git a/lab2/src/main/java/com/example/demo/tage/api/TageDto.java b/lab2/src/main/java/com/example/demo/tages/api/TageDto.java similarity index 94% rename from lab2/src/main/java/com/example/demo/tage/api/TageDto.java rename to lab2/src/main/java/com/example/demo/tages/api/TageDto.java index 3be894b..7d693eb 100644 --- a/lab2/src/main/java/com/example/demo/tage/api/TageDto.java +++ b/lab2/src/main/java/com/example/demo/tages/api/TageDto.java @@ -1,4 +1,4 @@ -package com.example.demo.tage.api; +package com.example.demo.tages.api; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/lab2/src/main/java/com/example/demo/tage/model/TageEntity.java b/lab2/src/main/java/com/example/demo/tages/model/TageEntity.java similarity index 57% rename from lab2/src/main/java/com/example/demo/tage/model/TageEntity.java rename to lab2/src/main/java/com/example/demo/tages/model/TageEntity.java index 3d67f0b..03ac5a8 100644 --- a/lab2/src/main/java/com/example/demo/tage/model/TageEntity.java +++ b/lab2/src/main/java/com/example/demo/tages/model/TageEntity.java @@ -1,12 +1,28 @@ -package com.example.demo.tage.model; +package com.example.demo.tages.model; +import java.util.HashSet; import java.util.Objects; +import java.util.Set; import com.example.demo.core.model.BaseEntity; import com.example.demo.news.model.NewEntity; +import com.example.demo.newtage.model.NewTageEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OrderBy; +import jakarta.persistence.Table; + +@Entity +@Table(name = "tages") public class TageEntity extends BaseEntity{ + @Column(nullable = false, unique = true, length = 50) private String text; + @OneToMany(mappedBy = "tages", cascade = CascadeType.ALL) + @OrderBy("id ASC") + private Set newTages = new HashSet<>(); public TageEntity() { super(); @@ -30,6 +46,10 @@ public class TageEntity extends BaseEntity{ return Objects.hash(id, text); } + public Set getNewTages() { + return newTages; + } + @Override public boolean equals(Object obj) { if (this == obj) diff --git a/lab2/src/main/java/com/example/demo/tages/repository/TageRepository.java b/lab2/src/main/java/com/example/demo/tages/repository/TageRepository.java new file mode 100644 index 0000000..ecc3662 --- /dev/null +++ b/lab2/src/main/java/com/example/demo/tages/repository/TageRepository.java @@ -0,0 +1,11 @@ +package com.example.demo.tages.repository; + +import java.util.Optional; + +import org.springframework.data.repository.CrudRepository; + +import com.example.demo.tages.model.TageEntity; + +public interface TageRepository extends CrudRepository { + Optional findByNameIgnoreCase(String name); +} diff --git a/lab2/src/main/java/com/example/demo/tages/service/TageService.java b/lab2/src/main/java/com/example/demo/tages/service/TageService.java new file mode 100644 index 0000000..be85542 --- /dev/null +++ b/lab2/src/main/java/com/example/demo/tages/service/TageService.java @@ -0,0 +1,63 @@ +package com.example.demo.tages.service; + +import java.util.List; +import java.util.stream.StreamSupport; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.example.demo.core.error.NotFoundException; +import com.example.demo.tages.model.TageEntity; +import com.example.demo.tages.repository.TageRepository; + + +@Service +public class TageService { + private final TageRepository repository; + + public TageService(TageRepository repository) { + this.repository = repository; + } + + private void checkTage(String tage) { + if (repository.findByNameIgnoreCase(tage).isPresent()) { + throw new IllegalArgumentException( + String.format("Type with tage %s is already exists", tage)); + } + } + + @Transactional(readOnly = true) + public List getAll() { + return StreamSupport.stream(repository.findAll().spliterator(), false).toList(); + } + + @Transactional(readOnly = true) + public TageEntity get(Long id) { + return repository.findById(id) + .orElseThrow(() -> new NotFoundException(TageEntity.class, id)); + } + + @Transactional + public TageEntity create(TageEntity entity) { + if (entity == null) { + throw new IllegalArgumentException("Entity is null"); + } + checkTage(entity.getText()); + return repository.save(entity); + } + + @Transactional + public TageEntity update(Long id, TageEntity entity) { + final TageEntity existsEntity = get(id); + checkTage(entity.getText()); + existsEntity.setText(entity.getText()); + return repository.save(existsEntity); + } + + @Transactional + public TageEntity delete(Long id) { + final TageEntity existsEntity = get(id); + repository.delete(existsEntity); + return existsEntity; + } +} diff --git a/lab2/src/main/java/com/example/demo/users/model/UserEntity.java b/lab2/src/main/java/com/example/demo/users/model/UserEntity.java index 79fedb9..dcac159 100644 --- a/lab2/src/main/java/com/example/demo/users/model/UserEntity.java +++ b/lab2/src/main/java/com/example/demo/users/model/UserEntity.java @@ -1,20 +1,37 @@ package com.example.demo.users.model; -import java.text.SimpleDateFormat; import java.util.Date; +import java.util.HashSet; import java.util.Objects; +import java.util.Set; +import com.example.demo.comments.model.CommentEntity; import com.example.demo.core.model.BaseEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OrderBy; +import jakarta.persistence.Table; + +@Entity +@Table(name = "users") public class UserEntity extends BaseEntity { + @Column(nullable = false, unique = true, length = 20) private String login; + @Column(nullable = false, unique = false, length = 20) private String password; + @Column(nullable = false, unique = false, length = 150) private String name; + @Column(nullable = false, unique = false, length = 50) private String email; private Date birthDate; + @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) + @OrderBy("id ASC") + private Set comments = new HashSet<>(); public UserEntity() { - super(); } public UserEntity(Long id, String login, String password, String name, String email, Date birthDate) { @@ -23,7 +40,6 @@ public class UserEntity extends BaseEntity { this.password = password; this.name = name; this.email = email; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); this.birthDate = birthDate; } @@ -67,6 +83,17 @@ public class UserEntity extends BaseEntity { this.birthDate = birthDate; } + public Set getComments() { + return comments; + } + + public void addComment(CommentEntity comment) { + if (comment.getUser() != this) { + comment.setUser(this); + } + comments.add(comment); + } + @Override public int hashCode() { return Objects.hash(id, login, password, name, email, birthDate); diff --git a/lab2/src/main/java/com/example/demo/users/repository/UserRepository.java b/lab2/src/main/java/com/example/demo/users/repository/UserRepository.java index fa4b654..5ede74f 100644 --- a/lab2/src/main/java/com/example/demo/users/repository/UserRepository.java +++ b/lab2/src/main/java/com/example/demo/users/repository/UserRepository.java @@ -1,10 +1,11 @@ package com.example.demo.users.repository; -import org.springframework.stereotype.Repository; +import java.util.Optional; + +import org.springframework.data.repository.CrudRepository; -import com.example.demo.core.repository.MapRepository; import com.example.demo.users.model.UserEntity; -@Repository -public class UserRepository extends MapRepository { +public interface UserRepository extends CrudRepository { + Optional findByLoginIgnoreCase(String login); } diff --git a/lab2/src/main/java/com/example/demo/users/service/UserService.java b/lab2/src/main/java/com/example/demo/users/service/UserService.java index c511d98..e125f6d 100644 --- a/lab2/src/main/java/com/example/demo/users/service/UserService.java +++ b/lab2/src/main/java/com/example/demo/users/service/UserService.java @@ -1,9 +1,10 @@ package com.example.demo.users.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.example.demo.core.error.NotFoundException; import com.example.demo.users.model.UserEntity; @@ -17,31 +18,49 @@ public class UserService { this.repository = repository; } + private void checkLogin(String login) { + if (repository.findByLoginIgnoreCase(login).isPresent()) { + throw new IllegalArgumentException( + String.format("Type with login %s is already exists", login)); + } + } + + @Transactional(readOnly = true) public List getAll() { - return repository.getAll(); + return StreamSupport.stream(repository.findAll().spliterator(), false).toList(); } + @Transactional(readOnly = true) public UserEntity get(Long id) { - return Optional.ofNullable(repository.get(id)) - .orElseThrow(() -> new NotFoundException(id)); + return repository.findById(id) + .orElseThrow(() -> new NotFoundException(UserEntity.class, id)); } + @Transactional public UserEntity create(UserEntity entity) { - return repository.create(entity); + if (entity == null) { + throw new IllegalArgumentException("Entity is null"); + } + checkLogin(entity.getLogin()); + return repository.save(entity); } + @Transactional public UserEntity update(Long id, UserEntity entity) { final UserEntity existsEntity = get(id); + checkLogin(entity.getLogin()); existsEntity.setLogin(entity.getLogin()); existsEntity.setPassword(entity.getPassword()); existsEntity.setName(entity.getName()); existsEntity.setEmail(entity.getEmail()); existsEntity.setBirthDate(entity.getBirthDate()); - return repository.update(existsEntity); + return repository.save(existsEntity); } + @Transactional public UserEntity delete(Long id) { final UserEntity existsEntity = get(id); - return repository.delete(existsEntity); + repository.delete(existsEntity); + return existsEntity; } } diff --git a/lab2/src/test/java/com/example/demo/CommentServiceTest.java b/lab2/src/test/java/com/example/demo/CommentServiceTest.java index d7c8810..fa6d987 100644 --- a/lab2/src/test/java/com/example/demo/CommentServiceTest.java +++ b/lab2/src/test/java/com/example/demo/CommentServiceTest.java @@ -1,6 +1,5 @@ package com.example.demo; -import java.util.Arrays; import java.util.Date; import org.junit.jupiter.api.Assertions; @@ -10,16 +9,16 @@ import org.junit.jupiter.api.TestMethodOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import com.example.demo.comment.model.CommentEntity; -import com.example.demo.comment.service.CommentService; +import com.example.demo.comments.model.CommentEntity; +import com.example.demo.comments.service.CommentService; import com.example.demo.core.error.NotFoundException; import com.example.demo.news.model.NewEntity; -import com.example.demo.tage.model.TageEntity; +import com.example.demo.tages.model.TageEntity; import com.example.demo.users.model.UserEntity; @SpringBootTest @TestMethodOrder(OrderAnnotation.class) -public class CommentServiceTest { +class CommentServiceTest { @Autowired private CommentService commentService; @@ -34,8 +33,7 @@ public class CommentServiceTest { //create var tage1 = new TageEntity(null, "пасха"); - var new1 = new NewEntity(null, "Чемпионат ICPC", new Date(), Arrays.asList(tage1), - "Студенты выступят на Чемпионате мира по программированию в Северной Евразии."); + var new1 = new NewEntity(null, "Чемпионат ICPC", new Date(), "Студенты выступят на Чемпионате мира по программированию в Северной Евразии."); var user1 = new UserEntity(null, "beko", "111", "ddwwdd", "beko@mail.ru", new Date()); diff --git a/lab2/src/test/java/com/example/demo/NewsServiceTest.java b/lab2/src/test/java/com/example/demo/NewsServiceTest.java index c1338b0..fb700f3 100644 --- a/lab2/src/test/java/com/example/demo/NewsServiceTest.java +++ b/lab2/src/test/java/com/example/demo/NewsServiceTest.java @@ -14,7 +14,7 @@ import org.springframework.boot.test.context.SpringBootTest; import com.example.demo.core.error.NotFoundException; import com.example.demo.news.model.NewEntity; import com.example.demo.news.service.NewService; -import com.example.demo.tage.model.TageEntity;; +import com.example.demo.tages.model.TageEntity;; @SpringBootTest @TestMethodOrder(OrderAnnotation.class) @@ -30,18 +30,18 @@ class NewsServiceTest { @Test void Test() { // create - List list1 = Arrays.asList - (new TageEntity(null, "праздник"), new TageEntity(null, "сессия")); + var tage1 = new TageEntity(null, "праздник"); + var tage2 = new TageEntity(null, "сессия"); - newsService.create(new NewEntity(null, "Название", new Date(), list1, "текст новости")); + newsService.create(new NewEntity(null, "Название", new Date(), "текст новости")); final NewEntity last = newsService.create - (new NewEntity(null, "9 апреля", new Date(), null, "просто наступил апрель")); + (new NewEntity(null, "9 апреля", new Date(), "просто наступил апрель")); Assertions.assertEquals(2L, newsService.getAll().size()); Assertions.assertEquals(last, newsService.get(2L)); // update - final var newNew = newsService.update(2L, new NewEntity(2L, "9 мая", new Date(), list1, "уже май!!!!!!!!!")); + final var newNew = newsService.update(2L, new NewEntity(2L, "9 мая", new Date(), "уже май!!!!!!!!!")); Assertions.assertEquals(2L, newsService.getAll().size()); Assertions.assertEquals(newNew, newsService.get(2L)); diff --git a/lab2/src/test/java/com/example/demo/TageServiceTest.java b/lab2/src/test/java/com/example/demo/TageServiceTest.java index 34be25b..a1b8922 100644 --- a/lab2/src/test/java/com/example/demo/TageServiceTest.java +++ b/lab2/src/test/java/com/example/demo/TageServiceTest.java @@ -8,13 +8,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import com.example.demo.core.error.NotFoundException; -import com.example.demo.tage.model.TageEntity; -import com.example.demo.tage.service.TageService; -import com.example.demo.users.model.UserEntity; +import com.example.demo.tages.model.TageEntity; +import com.example.demo.tages.service.TageService; @SpringBootTest @TestMethodOrder(OrderAnnotation.class) -public class TageServiceTest { +class TageServiceTest { @Autowired private TageService tageService;