feat: 初始化提交
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
package com.lanyuanxiaoyao.bookstore;
|
||||
|
||||
import com.blinkfox.fenix.EnableFenix;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
/**
|
||||
* 启动类
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250922
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableJpaAuditing
|
||||
@EnableFenix
|
||||
@EnableConfigurationProperties
|
||||
public class BookStoreApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BookStoreApplication.class, args);
|
||||
}
|
||||
}
|
||||
11
src/main/java/com/lanyuanxiaoyao/bookstore/Constants.java
Normal file
11
src/main/java/com/lanyuanxiaoyao/bookstore/Constants.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.lanyuanxiaoyao.bookstore;
|
||||
|
||||
/**
|
||||
* 静态变量
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250922
|
||||
*/
|
||||
public interface Constants {
|
||||
String DATABASE_PREFIX = "bookstore_";
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.lanyuanxiaoyao.bookstore.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* 网络配置
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250922
|
||||
*/
|
||||
@Configuration
|
||||
public class WebConfiguration {
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowCredentials(true);
|
||||
configuration.addAllowedOriginPattern("*");
|
||||
configuration.addAllowedHeader("*");
|
||||
configuration.addAllowedMethod("*");
|
||||
configuration.setMaxAge(7200L);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.lanyuanxiaoyao.bookstore.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Book;
|
||||
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
||||
import com.lanyuanxiaoyao.bookstore.service.BookService;
|
||||
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("book")
|
||||
public class BookController extends SimpleControllerSupport<Book, BookController.SaveItem, BookController.DetailItem, BookController.DetailItem> {
|
||||
private final BookService bookService;
|
||||
|
||||
public BookController(BookService service) {
|
||||
super(service);
|
||||
this.bookService = service;
|
||||
}
|
||||
|
||||
@GetMapping("tags")
|
||||
public List<Option> tags() {
|
||||
return bookService.tags();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<SaveItem, Book> saveItemMapper() {
|
||||
return item -> {
|
||||
Book book = new Book();
|
||||
book.setId(item.id());
|
||||
book.setName(item.name());
|
||||
book.setAuthor(item.author());
|
||||
book.setDescription(item.description());
|
||||
book.setSource(item.source());
|
||||
book.setTags(item.tags());
|
||||
return book;
|
||||
};
|
||||
}
|
||||
|
||||
private DetailItem toDetailItem(Book book) {
|
||||
return new DetailItem(
|
||||
book.getId(),
|
||||
book.getName(),
|
||||
book.getAuthor(),
|
||||
book.getDescription(),
|
||||
book.getSource(),
|
||||
book.getTags(),
|
||||
book.getCreatedTime(),
|
||||
book.getModifiedTime()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Book, DetailItem> listItemMapper() {
|
||||
return this::toDetailItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Book, DetailItem> detailItemMapper() {
|
||||
return this::toDetailItem;
|
||||
}
|
||||
|
||||
public record SaveItem(
|
||||
Long id,
|
||||
String name,
|
||||
String author,
|
||||
String description,
|
||||
String source,
|
||||
Set<String> tags
|
||||
) {
|
||||
}
|
||||
|
||||
public record DetailItem(
|
||||
Long id,
|
||||
String name,
|
||||
String author,
|
||||
String description,
|
||||
String source,
|
||||
Set<String> tags,
|
||||
LocalDateTime createdTime,
|
||||
LocalDateTime modifiedTime
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.lanyuanxiaoyao.bookstore.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Chapter;
|
||||
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
||||
import com.lanyuanxiaoyao.bookstore.service.BookService;
|
||||
import com.lanyuanxiaoyao.bookstore.service.ChapterService;
|
||||
import com.lanyuanxiaoyao.bookstore.service.LineService;
|
||||
import com.lanyuanxiaoyao.service.template.controller.GlobalResponse;
|
||||
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("chapter")
|
||||
public class ChapterController extends SimpleControllerSupport<Chapter, ChapterController.SaveItem, ChapterController.DetailItem, ChapterController.DetailItem> {
|
||||
private final ChapterService chapterService;
|
||||
private final BookService bookService;
|
||||
private final LineService lineService;
|
||||
|
||||
public ChapterController(ChapterService service, BookService bookService, LineService lineService) {
|
||||
super(service);
|
||||
this.chapterService = service;
|
||||
this.bookService = bookService;
|
||||
this.lineService = lineService;
|
||||
}
|
||||
|
||||
@GetMapping("chapters")
|
||||
public List<Option> chapters() {
|
||||
return chapterService.chapters();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Throwable.class)
|
||||
@PostMapping("save_with_content")
|
||||
public GlobalResponse<Object> saveWithContent(@RequestBody SaveWithContentItem item) {
|
||||
if (SaveWithContentItem.Mode.CREATE.equals(item.mode())) {
|
||||
var chapter = new Chapter();
|
||||
chapter.setSequence(chapterService.latestSequence(item.bookId()));
|
||||
chapter.setName(item.name());
|
||||
chapter.setDescription(item.description());
|
||||
chapter.setBook(bookService.detailOrThrow(item.bookId()));
|
||||
var chapterId = chapterService.save(chapter);
|
||||
lineService.load(chapterId, item.content());
|
||||
} else if (SaveWithContentItem.Mode.OVERRIDE.equals(item.mode())) {
|
||||
var chapter = chapterService.detailOrThrow(item.id());
|
||||
chapter.setName(item.name());
|
||||
chapter.setDescription(item.description());
|
||||
var chapterId = chapterService.save(chapter);
|
||||
lineService.empty(chapterId);
|
||||
lineService.load(chapterId, item.content());
|
||||
} else {
|
||||
return GlobalResponse.responseError("Invalid mode");
|
||||
}
|
||||
return GlobalResponse.responseSuccess();
|
||||
}
|
||||
|
||||
@GetMapping("generate_sequence")
|
||||
public GlobalResponse<Object> generateSequence() {
|
||||
chapterService.generateSequence();
|
||||
return GlobalResponse.responseSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<SaveItem, Chapter> saveItemMapper() {
|
||||
return item -> {
|
||||
var chapter = new Chapter();
|
||||
chapter.setId(item.id());
|
||||
chapter.setSequence(chapterService.latestSequence(item.bookId()));
|
||||
chapter.setName(item.name());
|
||||
chapter.setDescription(item.description());
|
||||
chapter.setBook(bookService.detailOrThrow(item.bookId()));
|
||||
return chapter;
|
||||
};
|
||||
}
|
||||
|
||||
private DetailItem toDetailItem(Chapter chapter) {
|
||||
return new DetailItem(
|
||||
chapter.getId(),
|
||||
chapter.getSequence(),
|
||||
chapter.getName(),
|
||||
chapter.getDescription(),
|
||||
chapter.getCreatedTime(),
|
||||
chapter.getModifiedTime()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Chapter, DetailItem> listItemMapper() {
|
||||
return this::toDetailItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Chapter, DetailItem> detailItemMapper() {
|
||||
return this::toDetailItem;
|
||||
}
|
||||
|
||||
public record SaveItem(
|
||||
Long id,
|
||||
Long bookId,
|
||||
String name,
|
||||
String description
|
||||
) {
|
||||
}
|
||||
|
||||
public record SaveWithContentItem(
|
||||
Long id,
|
||||
Long bookId,
|
||||
String name,
|
||||
String description,
|
||||
Mode mode,
|
||||
String content
|
||||
) {
|
||||
public SaveItem toSaveItem() {
|
||||
return new SaveItem(null, bookId, name, description);
|
||||
}
|
||||
|
||||
public enum Mode {
|
||||
CREATE, OVERRIDE
|
||||
}
|
||||
}
|
||||
|
||||
public record DetailItem(
|
||||
Long id,
|
||||
Long sequence,
|
||||
String name,
|
||||
String description,
|
||||
LocalDateTime createdTime,
|
||||
LocalDateTime modifiedTime
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.lanyuanxiaoyao.bookstore.controller;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Line;
|
||||
import com.lanyuanxiaoyao.bookstore.service.LineService;
|
||||
import com.lanyuanxiaoyao.service.template.controller.GlobalResponse;
|
||||
import com.lanyuanxiaoyao.service.template.controller.SimpleControllerSupport;
|
||||
import java.util.function.Function;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("line")
|
||||
public class LineController extends SimpleControllerSupport<Line, LineController.SaveItem, LineController.DetailItem, LineController.DetailItem> {
|
||||
private final LineService lineService;
|
||||
|
||||
public LineController(LineService service) {
|
||||
super(service);
|
||||
this.lineService = service;
|
||||
}
|
||||
|
||||
@PostMapping("load")
|
||||
public GlobalResponse<Object> load(@RequestBody LineController.LoadItem item) {
|
||||
lineService.load(item.chapterId(), item.content());
|
||||
return GlobalResponse.responseSuccess();
|
||||
}
|
||||
|
||||
@GetMapping("generate_sequence")
|
||||
public GlobalResponse<Object> generateSequence() {
|
||||
lineService.generateSequence();
|
||||
return GlobalResponse.responseSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<SaveItem, Line> saveItemMapper() {
|
||||
return item -> {
|
||||
var line = lineService.detailOrThrow(item.id());
|
||||
line.setText(item.text());
|
||||
return line;
|
||||
};
|
||||
}
|
||||
|
||||
private DetailItem toDetailItem(Line line) {
|
||||
return new DetailItem(
|
||||
line.getId(),
|
||||
line.getSequence(),
|
||||
line.getText()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Line, DetailItem> listItemMapper() {
|
||||
return this::toDetailItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Line, DetailItem> detailItemMapper() {
|
||||
return this::toDetailItem;
|
||||
}
|
||||
|
||||
public record SaveItem(
|
||||
Long id,
|
||||
Long chapterId,
|
||||
String text
|
||||
) {
|
||||
}
|
||||
|
||||
public record LoadItem(
|
||||
Long chapterId,
|
||||
String content
|
||||
) {
|
||||
}
|
||||
|
||||
public record DetailItem(
|
||||
Long id,
|
||||
Long sequence,
|
||||
String text
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
53
src/main/java/com/lanyuanxiaoyao/bookstore/entity/Book.java
Normal file
53
src/main/java/com/lanyuanxiaoyao/bookstore/entity/Book.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.lanyuanxiaoyao.bookstore.entity;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.Constants;
|
||||
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.CollectionTable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
* 书籍
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250922
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@Entity
|
||||
@DynamicUpdate
|
||||
@DynamicInsert
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
@Table(name = Constants.DATABASE_PREFIX + "book")
|
||||
public class Book extends SimpleEntity {
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
private String author;
|
||||
private String description;
|
||||
private String source;
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = Constants.DATABASE_PREFIX + "book_tags", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
private Set<String> tags;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "book")
|
||||
@ToString.Exclude
|
||||
private Set<Chapter> chapters;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.lanyuanxiaoyao.bookstore.entity;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.Constants;
|
||||
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
* 章节
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250922
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@Entity
|
||||
@DynamicUpdate
|
||||
@DynamicInsert
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
@Table(name = Constants.DATABASE_PREFIX + "chapter")
|
||||
public class Chapter extends SimpleEntity {
|
||||
@Column(nullable = false)
|
||||
private Long sequence;
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
|
||||
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
@ToString.Exclude
|
||||
private Book book;
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "chapter")
|
||||
@ToString.Exclude
|
||||
private Set<Line> content;
|
||||
}
|
||||
53
src/main/java/com/lanyuanxiaoyao/bookstore/entity/Line.java
Normal file
53
src/main/java/com/lanyuanxiaoyao/bookstore/entity/Line.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.lanyuanxiaoyao.bookstore.entity;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.Constants;
|
||||
import com.lanyuanxiaoyao.service.template.entity.SimpleEntity;
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.FieldNameConstants;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
/**
|
||||
* 书籍行
|
||||
*
|
||||
* @author lanyuanxiaoyao
|
||||
* @version 20250922
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString(callSuper = true)
|
||||
@FieldNameConstants
|
||||
@Entity
|
||||
@DynamicUpdate
|
||||
@DynamicInsert
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
@Table(name = Constants.DATABASE_PREFIX + "line")
|
||||
public class Line extends SimpleEntity {
|
||||
@Column(nullable = false)
|
||||
private Long sequence;
|
||||
@Lob
|
||||
@Basic(fetch = FetchType.LAZY)
|
||||
@ToString.Exclude
|
||||
@Column(nullable = false)
|
||||
private String text;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
|
||||
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
|
||||
@ToString.Exclude
|
||||
private Chapter chapter;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.lanyuanxiaoyao.bookstore.entity.vo;
|
||||
|
||||
/**
|
||||
* Amis Option
|
||||
*
|
||||
* @author 选项
|
||||
* @version 20250923
|
||||
*/
|
||||
public record Option(String label, Object value) {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lanyuanxiaoyao.bookstore.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Book;
|
||||
import com.lanyuanxiaoyao.service.template.repository.SimpleRepository;
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface BookRepository extends SimpleRepository<Book> {
|
||||
@Query("select distinct book.tags from Book book")
|
||||
List<String> findDistinctTags();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.lanyuanxiaoyao.bookstore.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Chapter;
|
||||
import com.lanyuanxiaoyao.service.template.repository.SimpleRepository;
|
||||
import java.util.Optional;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface ChapterRepository extends SimpleRepository<Chapter> {
|
||||
@Query("select max(chapter.sequence) from Chapter chapter")
|
||||
Optional<Long> findMaxSequence(Long bookId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.lanyuanxiaoyao.bookstore.repository;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Line;
|
||||
import com.lanyuanxiaoyao.service.template.repository.SimpleRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface LineRepository extends SimpleRepository<Line> {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.lanyuanxiaoyao.bookstore.service;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Book;
|
||||
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
||||
import com.lanyuanxiaoyao.bookstore.repository.BookRepository;
|
||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BookService extends SimpleServiceSupport<Book> {
|
||||
private final BookRepository bookRepository;
|
||||
|
||||
public BookService(BookRepository repository) {
|
||||
super(repository);
|
||||
this.bookRepository = repository;
|
||||
}
|
||||
|
||||
public List<Option> tags() {
|
||||
return bookRepository.findDistinctTags()
|
||||
.stream()
|
||||
.map(tag -> new Option(tag, tag))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.lanyuanxiaoyao.bookstore.service;
|
||||
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Chapter;
|
||||
import com.lanyuanxiaoyao.bookstore.entity.vo.Option;
|
||||
import com.lanyuanxiaoyao.bookstore.repository.ChapterRepository;
|
||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ChapterService extends SimpleServiceSupport<Chapter> {
|
||||
private final ChapterRepository chapterRepository;
|
||||
|
||||
public ChapterService(ChapterRepository repository) {
|
||||
super(repository);
|
||||
this.chapterRepository = repository;
|
||||
}
|
||||
|
||||
public List<Option> chapters() {
|
||||
return list()
|
||||
.stream()
|
||||
.map(chapter -> new Option(chapter.getName(), chapter.getId()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
public Long latestSequence(Long bookId) {
|
||||
return chapterRepository.findMaxSequence(bookId).orElse(0L);
|
||||
}
|
||||
|
||||
public void generateSequence() {
|
||||
var chapters = chapterRepository.findAll(Sort.by(Sort.Direction.ASC, Chapter.Fields.sequence));
|
||||
for (int index = 0; index < chapters.size(); index++) {
|
||||
chapters.get(index).setSequence((long) index);
|
||||
}
|
||||
chapterRepository.saveAll(chapters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.lanyuanxiaoyao.bookstore.service;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.lanyuanxiaoyao.bookstore.entity.Line;
|
||||
import com.lanyuanxiaoyao.bookstore.repository.LineRepository;
|
||||
import com.lanyuanxiaoyao.service.template.entity.IdOnlyEntity;
|
||||
import com.lanyuanxiaoyao.service.template.service.SimpleServiceSupport;
|
||||
import java.util.stream.Stream;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LineService extends SimpleServiceSupport<Line> {
|
||||
private final LineRepository lineRepository;
|
||||
|
||||
private final ChapterService chapterService;
|
||||
|
||||
public LineService(LineRepository repository, ChapterService chapterService) {
|
||||
super(repository);
|
||||
this.lineRepository = repository;
|
||||
this.chapterService = chapterService;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Throwable.class)
|
||||
public void load(Long chapterId, String text) {
|
||||
var chapter = chapterService.detailOrThrow(chapterId);
|
||||
var lines = Stream.of(text.split("\n"))
|
||||
.map(StrUtil::trimToNull)
|
||||
.filter(ObjectUtil::isNotNull)
|
||||
.toList();
|
||||
for (int index = 0; index < lines.size(); index++) {
|
||||
var line = new Line();
|
||||
line.setSequence((long) index);
|
||||
line.setText(lines.get(index));
|
||||
line.setChapter(chapter);
|
||||
lineRepository.save(line);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Throwable.class)
|
||||
public void empty(Long chapterId) {
|
||||
repository.delete((root, query, builder) -> builder.equal(root.get(Line.Fields.chapter).get(IdOnlyEntity.Fields.id), chapterId));
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Throwable.class)
|
||||
public void generateSequence() {
|
||||
var lines = lineRepository.findAll(Sort.by(Sort.Direction.ASC, Line.Fields.sequence));
|
||||
for (int index = 0; index < lines.size(); index++) {
|
||||
lines.get(index).setSequence((long) index);
|
||||
}
|
||||
lineRepository.saveAll(lines);
|
||||
}
|
||||
}
|
||||
|
||||
28
src/main/resources/application.yml
Normal file
28
src/main/resources/application.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
server:
|
||||
port: 27891
|
||||
compression:
|
||||
enabled: true
|
||||
spring:
|
||||
application:
|
||||
name: bookstore
|
||||
mvc:
|
||||
async:
|
||||
request-timeout: 3600000
|
||||
datasource:
|
||||
url: jdbc:h2:file:./bookstore;DB_CLOSE_ON_EXIT=TRUE
|
||||
username: bookstore
|
||||
password: bookstore
|
||||
driver-class-name: org.h2.Driver
|
||||
jpa:
|
||||
generate-ddl: false
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
main:
|
||||
banner-mode: off
|
||||
fenix:
|
||||
print-banner: false
|
||||
liteflow:
|
||||
enable: false
|
||||
print-banner: false
|
||||
check-node-exists: false
|
||||
rule-source: flow.xml
|
||||
6
src/main/resources/flow.xml
Normal file
6
src/main/resources/flow.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE flow PUBLIC "liteflow" "https://liteflow.cc/liteflow.dtd">
|
||||
<flow>
|
||||
<chain name="empty">
|
||||
</chain>
|
||||
</flow>
|
||||
24
src/main/resources/logback-spring.xml
Normal file
24
src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
|
||||
<conversionRule conversionWord="clr" class="org.springframework.boot.logging.logback.ColorConverter"/>
|
||||
<conversionRule conversionWord="wex" class="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
|
||||
<conversionRule conversionWord="wEx" class="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
|
||||
|
||||
<springProperty scope="context" name="LOGGING_PARENT" source="logging.parent"/>
|
||||
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
|
||||
|
||||
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%5p) %clr([${HOSTNAME}]){yellow} %clr([%t]){magenta} %clr(%logger{40}){cyan}: %m%n%wEx
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="com.lanyuanxiaoyao.leopard" level="INFO"/>
|
||||
<logger name="org.hibernate.SQL" level="DEBUG"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="Console"/>
|
||||
</root>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user