Fix database structure#183
Open
TheMeinerLP wants to merge 33 commits intomainfrom
Open
Conversation
Contributor
TheMeinerLP
commented
Apr 18, 2026
- fix(db): stop closing shared SessionFactory in flag service
- fix(db): return HomePosition model from entityToModel mapper
- fix(db): fail fast when the Hibernate SessionFactory cannot be built
- fix(plugin): disable plugin cleanly when bootstrap throws
- fix(db): correct chunk-removal return value and parameter binding
- fix(db): tighten transaction boundaries in land service
- fix(db): add explicit join columns and id-based equality to LandEntity
- fix(db): make FlagContainerEntity the inverse side of the Land link
- fix(db): switch LandMemberEntity.member to ManyToOne
- fix(db): add unique, NOT NULL and length constraints to LandPlayerEntity
- fix(db): enforce NOT NULL on HomePositionEntity columns
- fix(db): add name column and id-based equality to LandAreaEntity
- fix(db): prevent duplicate claims on the same chunk
- fix(db): constrain LandRoleFlagEntity columns and de-duplicate
- fix(db): constrain LandNaturalFlagEntity columns and de-duplicate
- fix(db): constrain LandEntityCapFlagEntity columns and de-duplicate
- fix(db): use ClaimedChunkMappingStrategy for chunk mapping
- fix(db): use per-flag strategies when mapping FlagContainer children
- docs(db): document session-open requirement for LandMappingStrategy
- chore(config): consolidate entity mappings into common/hibernate.cfg.xml
- chore(config): drop duplicate plugin-side hibernate.cfg.xml
- chore(test): run common tests against in-memory H2
- chore(build): pull in H2 for the common test classpath
- chore(test): remove obsolete constants.kt
- chore(test): remove obsolete TestDatabaseServiceImpl.kt
- chore(test): remove obsolete TestLandFlagService.kt
- chore(test): remove obsolete TestLandPlayerService.kt
- chore(test): remove obsolete TestLandService.kt
- chore(test): remove obsolete TestPandorasClusterApiImpl.kt
- chore(build): drop unused Liquibase plugin alias
- chore(build): drop Liquibase and migrate Shadow to com.gradleup.shadow
Each of the 9 flag operations wrapped the SessionFactory in try-with-resources, closing the shared singleton after the first call. Subsequent flag operations then failed with "SessionFactory is closed". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The entity-to-model direction was constructing a new HomePositionEntity instead of the HomePosition API model, so callers received an entity where they expected the DTO. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously a HibernateException was swallowed, databaseService was left null, and the plugin continued to enable with null service references, NPEing on the first command. Throw IllegalStateException instead so the plugin entry point can log and disable cleanly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrap the PandorasClusterImpl construction in onEnable so a failed Hibernate bootstrap no longer leaves the plugin half-initialized — the PluginManager disables the plugin and the error is surfaced in the log. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- removeClaimedChunk hard-coded return false, so callers never saw a successful deletion. - getClaimedChunk declared a :chunkIndex named parameter but never bound it, making the query return an arbitrary row. - Document unclaimArea as a best-effort composition of already- transactional sub-operations so future readers do not assume atomicity. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- createLand now persists the land, its home, its flag container, the default LandArea and its initial ClaimedChunk in a single transaction so a partial failure rolls back cleanly. Previously the area creation ran after the outer commit, leaving orphan rows on exception. - unclaimLand moves its cross-service sub-calls (removeFlagsFromLand, landAreaService::unclaimArea) outside the session, then loads the LandEntity by id and removes it along with its HomePositionEntity. The old code called session.remove(land) with the API model. - getLands eagerly fetches owner, home, flagContainer and areas to prevent LazyInitializationException after the session closes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Without @joincolumn, Hibernate generated implementation-defined FK column names. Bind owner/home/flagContainerEntity to owner_id, home_id and flag_container_id respectively, all NOT NULL, and mark the flag_container side as the owning side of the OneToOne (the inverse mappedBy moves to FlagContainerEntity). Add id-based equals/hashCode with a null-id identity fallback. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the unmapped OneToOne so the LandEntity side alone owns the FK column (flag_container_id). Add id-based equals/hashCode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A player can be a member of multiple land areas, so the OneToOne was semantically wrong — the second addLandMember for the same player would violate the uniqueness implied by OneToOne. Also add an explicit member_id join column. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace dialect-specific columnDefinition with portable length / nullable / unique annotations. uuid becomes the natural unique key (length 36), name is length 16 NOT NULL. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A position without world + coordinates has no meaning; declare every column non-nullable and give world a 64-char bound. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
name had no @column annotation, so Hibernate generated an unbounded nullable column. Declare length 64 NOT NULL and add id-based equals/hashCode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rename chunkIndex to chunk_index and add a composite unique constraint on (landArea_id, chunk_index) so the same chunk can no longer be claimed twice in the same area. Also add id-based equals/hashCode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add length/NOT NULL on name, state, role and flagContainer_id, plus a uk_role_flags_container_name unique constraint so the same role flag cannot be persisted twice for one container. Add id-based equality. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add length/NOT NULL on name, state and flagContainer_id, plus a uk_natural_flags_container_name unique constraint. Add id-based equality. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add length/NOT NULL on name, spawn_limit and flagContainer_id, plus a uk_entitycap_flags_container_name unique constraint. Add id-based equality. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
getChunks was feeding ClaimedChunkDto instances into a new LandAreaMappingStrategy, so the instanceof check failed and every chunk came back null. Use ClaimedChunkMappingStrategy.create() instead. Also document that the strategy must run inside an open Hibernate session. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The three flag collections were previously mapped through a single LandMappingStrategy instance, so every NaturalFlag / RoleFlag / EntityCapFlag failed the instanceof check and came back null. Wire each collection to its own NaturalFlagMappingStrategy / RoleFlagMappingStrategy / EntityCapFlagMappingStrategy and keep the land link on its own context. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The common module builds the SessionFactory, so the <mapping class="…"/> list lives here. The plugin-side hibernate.cfg.xml becomes redundant and is removed in a follow-up commit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entity mappings now live in common/hibernate.cfg.xml. Keeping two copies invited drift — the plugin copy had the mappings while the common copy had the dialect/connection block. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The test config pointed at localhost PostgreSQL, so a developer needed a running Postgres container to execute :common:test. Switch to an in-memory H2 database with H2Dialect and create-drop so tests can run in isolation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New in-memory test configuration in connection.cfg.xml needs the H2 driver at runtime for :common:test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The common module does not apply the Kotlin plugin, so this test support file never compiled. It also referenced DBO classes that were removed long ago. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dead test support code referencing removed DatabaseService contract. Common module has no Kotlin plugin applied so it never compiled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dead test support code referencing removed DBO types. Common module has no Kotlin plugin applied so it never compiled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dead test support code referencing removed DBO types. Common module has no Kotlin plugin applied so it never compiled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dead test support code referencing removed DBO types. Common module has no Kotlin plugin applied so it never compiled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Dead test support code referencing a removed PandorasClusterApi interface and the wrong service constructors. Common module has no Kotlin plugin applied so it never compiled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The liquibase Gradle plugin was applied but never configured — no
changelog file, no liquibase {} block, no activities. Schema is owned
by Hibernate via hbm2ddl.auto=update, so remove the dead alias.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove the unused liquibase version/plugin entries. Schema is owned by Hibernate via hbm2ddl.auto=update. - Bump Shadow 8.1.1 → 9.4.1 and switch plugin id from the archived com.github.johnrengelman.shadow to com.gradleup.shadow so shadowJar works under Gradle 9.x. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…chException Hibernate 7 rejects JOIN FETCH-ing two bag-style List collections in the same query. The LandAreaEntity has two such bags (members and chunks), so the original query failed at translation time with "cannot simultaneously fetch multiple bags". Fetch the area together with its parent land in the primary query, then initialize the two bag collections separately via Hibernate.initialize(). Still inside the session, so the mapper can walk them without a LazyInitializationException. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After home_id and flag_container_id became NOT NULL, Hibernate started throwing TransientPropertyValueException because LandEntity was persisted before its HomePositionEntity. Reorder so: 1. home and flag container (no outgoing non-null FKs) are persisted first 2. owner is referenced via session.getReference (player already exists) 3. landEntity is persisted once all three FKs point at managed entities 4. area and its initial chunk follow This also drops the flagContainer.withLand(landEntity) call — after Phase 3, FlagContainerEntity.land is mappedBy and carries no FK column, so the back-reference is purely ornamental at persist time. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.