Changes between Version 5 and Version 6 of AdvancedApplicationDevelopment


Ignore:
Timestamp:
08/06/26 13:02:26 (34 hours ago)
Author:
231175
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedApplicationDevelopment

    v5 v6  
    1111
    1212        Course course = buildCourse(courseDtoFull, language);
     13        course = courseRepository.save(course);
    1314
    1415        CourseVersion oldCourseVersion = courseVersionRepository
    15                 .findByActiveTrueAndCourse_Id(course.getId());
     16                .findByIsActiveTrueAndCourse_CourseId(course.getCourseId());
    1617
    1718        int newVersionNumber = 1;
    1819        if (oldCourseVersion != null) {
    1920            newVersionNumber = oldCourseVersion.getVersionNumber() + 1;
    20             oldCourseVersion.setActive(false);
     21            oldCourseVersion.setIsActive(false);
    2122            courseVersionRepository.save(oldCourseVersion);
    2223        }
     
    2425        CourseVersion courseVersion = CourseVersion.builder()
    2526                .versionNumber(newVersionNumber)
    26                 .active(true)
    27                 .creationDate(java.time.LocalDate.now())
     27                .isActive(true)
     28                .createdAt(java.time.LocalDate.now())
    2829                .course(course)
    2930                .build();
     
    9091        validate.validateCourseTranslation(courseTranslateReq.getId(), courseTranslateReq.getLanguage());
    9192
    92         CourseVersion courseVersion = courseVersionRepository.findByActiveTrueAndCourse_Id(courseTranslateReq.getId());
     93        CourseVersion courseVersion = courseVersionRepository.findByIsActiveTrueAndCourse_CourseId(courseTranslateReq.getId());
    9394        Course course = courseRepository.findById(courseTranslateReq.getId()).orElseThrow();
    9495        addCourseTranslation(course, courseTranslateReq);
     
    123124        for (CourseContent content : courseVersion.getCourseContents()) {
    124125            CourseContentTranslateReq contentDto = contentDtos.stream()
    125                     .filter(ct -> ct.getId().equals(content.getId()))
     126                    .filter(ct -> ct.getId().equals(content.getCourseContentId()))
    126127                    .findFirst()
    127128                    .orElseThrow(() -> new RuntimeException(
    128                             "Missing translation DTO for CourseContent id=" + content.getId()
     129                            "Missing translation DTO for CourseContent id=" + content.getCourseContentId()
    129130                    ));
    130131
     
    147148        for (CourseLecture lecture : content.getCourseLectures()) {
    148149            CourseLectureTranslateReq lectureDto = lectureDtos.stream()
    149                     .filter(ld -> ld.getId().equals(lecture.getId()))
     150                    .filter(ld -> ld.getId().equals(lecture.getCourseLectureId()))
    150151                    .findFirst()
    151152                    .orElseThrow(() -> new RuntimeException(
    152                             "Missing translation DTO for CourseLecture id=" + lecture.getId()
     153                            "Missing translation DTO for CourseLecture id=" + lecture.getCourseLectureId()
    153154                    ));
    154155
     
    157158                    .title(lectureDto.getTitle())
    158159                    .description(lectureDto.getDescription())
     160                    .contentFileName(lectureDto.getContentFileName())
    159161                    .contentText(lectureDto.getContentText())
    160162                    .courseLecture(lecture)
     
    166168}}}
    167169
     170== Мапирање на ентитети кон новата шема ==
     171
     172Новата шема користи PostgreSQL enum типови и `text[]` колона, кои Hibernate не ги мапира автоматски.
     173
     174Enum вредностите во базата се со мали букви (`skill`, `topic`, `beginner`, `pending`, ...), затоа Java enum константите мора да ги носат истите имиња преку `@JdbcTypeCode(SqlTypes.NAMED_ENUM)`.
     175{{{
     176@Entity
     177@Table(name = "tag")
     178public class Tag {
     179
     180    @Id
     181    @GeneratedValue(strategy = GenerationType.IDENTITY)
     182    @Column(name = "tag_id")
     183    private Long tagId;
     184
     185    @Enumerated(EnumType.STRING)
     186    @JdbcTypeCode(SqlTypes.NAMED_ENUM)
     187    @Column(name = "tag_type", columnDefinition = "tag_type")
     188    private TagType tagType;
     189}
     190
     191public enum TagType {
     192    skill,
     193    topic
     194}
     195}}}
     196
     197Колоната `what_will_be_learned` е `text[]`, па се мапира како `List<String>`.
     198{{{
     199@Entity
     200@Table(name = "course_translate")
     201public class CourseTranslate {
     202
     203    @Id
     204    @GeneratedValue(strategy = GenerationType.IDENTITY)
     205    @Column(name = "course_translate_id")
     206    private Long courseTranslateId;
     207
     208    @JdbcTypeCode(SqlTypes.ARRAY)
     209    @Column(name = "what_will_be_learned", columnDefinition = "text[]")
     210    private List<String> whatWillBeLearned;
     211
     212    @ManyToOne(fetch = FetchType.LAZY)
     213    @JoinColumn(name = "language_id")
     214    private Language language;
     215
     216    @ManyToOne(fetch = FetchType.LAZY)
     217    @JoinColumn(name = "course_id")
     218    private Course course;
     219}
     220}}}
     221
     222Табелата `user` е резервиран збор во PostgreSQL, па името мора да биде во наводници.
     223{{{
     224@Entity
     225@Table(name = "\"user\"")
     226public class User {
     227
     228    @Id
     229    @GeneratedValue(strategy = GenerationType.IDENTITY)
     230    @Column(name = "user_id")
     231    private Long userId;
     232
     233    @Column(name = "is_verified")
     234    private Boolean isVerified;
     235
     236    @Column(name = "is_profile_complete")
     237    private Boolean isProfileComplete;
     238
     239    @Column(name = "has_used_free_consultation")
     240    private Boolean hasUsedFreeConsultation;
     241
     242    @ManyToOne(fetch = FetchType.LAZY)
     243    @JoinColumn(name = "account_id")
     244    private Account account;
     245}
     246}}}
     247
    168248== Pooling ==
    169249
    170250Pooling претставува процес каде што не се отвара нова конекција за секој request, туку има константен број на отворени конекции кои се доделуваат на различни requests. Со ова значително се намалува времето по request бидејќи не се губи време за отварање на нова и затворање на стара конекција.
    171251
    172 Во мојот проект ова го правам со Hikari Pool во Java Spring Boot. Hikari е автоматски вклучено во Spring Boot (не треба дополнителна конфигурација за користење) преку spring-boot-starter-web библиотеката.
     252Во мојот проект ова го правам со Hikari Pool во Java Spring Boot. Hikari е автоматски вклучено во Spring Boot (не треба дополнителна конфигурација за користење) преку spring-boot-starter-data-jpa библиотеката.
    173253{{{
    174254<dependency>
    175255        <groupId>org.springframework.boot</groupId>
    176         <artifactId>spring-boot-starter-web</artifactId>
     256        <artifactId>spring-boot-starter-data-jpa</artifactId>
    177257</dependency>
    178258}}}
     
    197277# Максимално времетраење на една конекција (пред да биде заменета со нова)
    198278spring.datasource.hikari.max-lifetime=1800000
    199 }}}
     279
     280# Дозволува драјверот да праќа стрингови без експлицитен тип, за PostgreSQL enum колоните
     281spring.datasource.hikari.data-source-properties.stringtype=unspecified
     282}}}