feat: add Firearm and Modification entities with database schema

This commit is contained in:
2026-04-03 14:29:04 +08:00
parent 7c249ee4be
commit 8053bbb6b6
7 changed files with 441 additions and 32 deletions
+142 -29
View File
@@ -1,37 +1,150 @@
HELP.md ### macOS
.gradle # General
build/ .DS_Store
!gradle/wrapper/gradle-wrapper.jar .AppleDouble
!**/src/main/**/build/ .LSOverride
!**/src/test/**/build/
### STS ### # Thumbnails
.apt_generated ._*
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ### # Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Linux
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# Metadata left by Dolphin file manager, which comes with KDE Plasma
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# Log files created by default by the nohup command
nohup.out
### Windows
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### JetBrains IDE
# Covers JetBrains IDEs: IntelliJ, GoLand, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea .idea
*.iws
# Gradle and Maven with auto-import
*.iml *.iml
*.ipr *.ipr
# File-based project format
*.iws
# IntelliJ
out/ out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ### # JIRA plugin
/nbproject/private/ atlassian-ide-plugin.xml
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ### # Crashlytics plugin (for Android Studio and IntelliJ)
.vscode/ com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based HTTP Client
http-client.private.env.json
### Server
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.jar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
# Config
config/*.yml
config/*.yaml
config/*.properties
# Tests
test/
### Gradle
.gradle
**/build/
!**/src/**/build/
!gradle/
!gradle/wrapper
!gradle/wrapper/gradle-wrapper.jar
!gradle/wrapper/gradle-wrapper.properties
gradle-app.setting
.gradletasknamecache
# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath
+3 -2
View File
@@ -48,13 +48,14 @@ dependencies {
implementation(libs.spring.boot.starter.jpa) implementation(libs.spring.boot.starter.jpa)
implementation(libs.mybatis.starter.core) implementation(libs.mybatis.starter.core)
implementation(libs.flyway.core) implementation(libs.flyway.core)
implementation(libs.flyway.postgresql) implementation(libs.flyway.mysql)
implementation(libs.jackson.jsr310) implementation(libs.jackson.jsr310)
testImplementation(libs.spring.boot.starter.test) testImplementation(libs.spring.boot.starter.test)
testImplementation(libs.reactor.test) testImplementation(libs.reactor.test)
testImplementation(libs.spring.security.test) testImplementation(libs.spring.security.test)
testImplementation(libs.mybatis.starter.test) testImplementation(libs.mybatis.starter.test)
runtimeOnly(libs.postgres.driver) // runtimeOnly(libs.postgres.driver)
runtimeOnly(libs.mysql.driver)
testRuntimeOnly(libs.h2.database) testRuntimeOnly(libs.h2.database)
testRuntimeOnly(libs.junit.launcher) testRuntimeOnly(libs.junit.launcher)
} }
+2
View File
@@ -41,10 +41,12 @@ mybatis-starter-core = { group = "org.mybatis.spring.boot", name = "mybatis-spri
spring-boot-starter-jpa = { group = "org.springframework.boot", name = "spring-boot-starter-data-jpa" } spring-boot-starter-jpa = { group = "org.springframework.boot", name = "spring-boot-starter-data-jpa" }
hypersistence-core = { group = "io.hypersistence", name = "hypersistence-utils-hibernate-63", version.ref = "hypersistenceVersion" } hypersistence-core = { group = "io.hypersistence", name = "hypersistence-utils-hibernate-63", version.ref = "hypersistenceVersion" }
postgres-driver = { group = "org.postgresql", name = "postgresql", version.ref = "postgresDriverVersion" } postgres-driver = { group = "org.postgresql", name = "postgresql", version.ref = "postgresDriverVersion" }
mysql-driver = { group = "com.mysql", name = "mysql-connector-j" }
h2-database = { group = "com.h2database", name = "h2", version.ref = "h2Version" } h2-database = { group = "com.h2database", name = "h2", version.ref = "h2Version" }
spring-boot-starter-redis = { group = "org.springframework.boot", name = "spring-boot-starter-data-redis", version.ref = "springBootVersion" } spring-boot-starter-redis = { group = "org.springframework.boot", name = "spring-boot-starter-data-redis", version.ref = "springBootVersion" }
flyway-core = { group = "org.flywaydb", name = "flyway-core" } flyway-core = { group = "org.flywaydb", name = "flyway-core" }
flyway-postgresql = { group = "org.flywaydb", name = "flyway-database-postgresql" } flyway-postgresql = { group = "org.flywaydb", name = "flyway-database-postgresql" }
flyway-mysql = { group = "org.flywaydb", name = "flyway-mysql" }
# Spring Boot Core & Web # Spring Boot Core & Web
spring-boot-starter-web = { group = "org.springframework.boot", name = "spring-boot-starter-web" } spring-boot-starter-web = { group = "org.springframework.boot", name = "spring-boot-starter-web" }
@@ -0,0 +1,96 @@
package com.onixbyte.deltaforceguide.domain.entity;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "firearm")
public class Firearm {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name", nullable = false, length = 64)
private String name;
@Column(name = "type", nullable = false)
private Integer type;
@Column(name = "level", nullable = false)
private Integer level;
@Column(name = "review", columnDefinition = "TEXT")
private String review;
@OneToMany(mappedBy = "firearm", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Modification> modifications = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public String getReview() {
return review;
}
public void setReview(String review) {
this.review = review;
}
public List<Modification> getModifications() {
return modifications;
}
public void setModifications(List<Modification> modifications) {
this.modifications = modifications;
}
public void addModification(Modification modification) {
this.modifications.add(modification);
modification.setFirearm(this);
}
public void removeModification(Modification modification) {
this.modifications.remove(modification);
modification.setFirearm(null);
}
}
@@ -0,0 +1,120 @@
package com.onixbyte.deltaforceguide.domain.entity;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import org.hibernate.annotations.Type;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(
name = "modification",
indexes = {
@Index(name = "idx_modification_firearm_id", columnList = "firearm_id")
}
)
public class Modification {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "firearm_id", nullable = false, foreignKey = @ForeignKey(name = "fk_modification_firearm"))
private Firearm firearm;
@Column(name = "name", nullable = false, length = 64)
private String name;
@Column(name = "code", nullable = false, length = 64)
private String code;
@Type(JsonType.class)
@Column(name = "tags", columnDefinition = "json")
private List<String> tags = new ArrayList<>();
@Column(name = "note", columnDefinition = "TEXT")
private String note;
@Column(name = "author", length = 64)
private String author;
@Column(name = "video_url", length = 512)
private String videoUrl;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Firearm getFirearm() {
return firearm;
}
public void setFirearm(Firearm firearm) {
this.firearm = firearm;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getVideoUrl() {
return videoUrl;
}
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
}
+44 -1
View File
@@ -1,3 +1,46 @@
spring: spring:
application: application:
name: delta-force-guide-server name: delta-force-guide
cache:
type: redis
redis:
time-to-live: PT2H
data:
redis:
repositories:
# Disable redis repositories
enabled: false
jta:
# Disable JTA support
enabled: false
jpa:
properties:
hibernate:
transaction:
jta:
# No need to use distributed transaction manager for 1 datasource.
platform: org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform
hibernate:
ddl-auto: none
open-in-view: false
datasource:
hikari:
minimum-idle: 1
maximum-pool-size: 10
flyway:
enabled: true
baseline-on-migrate: true
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
map-underscore-to-camel-case: true
type-aliases-package: com.onixbyte.deltaforceguide.domain.entity
type-handlers-package: com.onixbyte.deltaforceguide.mapper.handler
mapper-locations: classpath:/mapper/*.xml
logging:
level:
org.hibernate:
orm.connections.pooling: off
@@ -0,0 +1,34 @@
DROP TABLE IF EXISTS firearm CASCADE;
DROP TABLE IF EXISTS modification CASCADE;
CREATE TABLE IF NOT EXISTS firearm
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(64) NOT NULL,
type INT NOT NULL,
level INT NOT NULL,
review TEXT NULL
);
CREATE TABLE IF NOT EXISTS modification
(
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
firearm_id BIGINT NOT NULL,
name VARCHAR(64) NOT NULL,
code VARCHAR(64) NOT NULL,
tags JSON NULL,
note TEXT NULL,
author VARCHAR(64) NULL,
video_url VARCHAR(512) NULL,
CONSTRAINT fk_modification_firearm
FOREIGN KEY (firearm_id)
REFERENCES firearm (id)
ON DELETE CASCADE
ON UPDATE RESTRICT
);
CREATE INDEX idx_modification_firearm_id ON modification (firearm_id);