From 3fb4232913aedf3b069b33d71fc0134c4b7ab132 Mon Sep 17 00:00:00 2001 From: Martin Korotwitschka Date: Mon, 5 Feb 2024 16:10:22 +0100 Subject: [PATCH] Kinda repaired lazy load for location Primarly bcs endpoint for myrek --- .../api/table/enemy/model/Enemy.java | 3 +- .../api/table/enemy/model/dto/EnemyDTO.java | 10 ++-- .../schematic/hex/model/dto/HexEnemyDTO.java | 5 +- .../hex/model/dto/HexObstacleDTO.java | 7 ++- .../location/LocationController.java | 17 ++++--- .../schematic/location/model/Location.java | 25 ++++++++++ .../location/model/dto/LocationDTO.java | 50 +++++++++---------- .../schematic/obstacle/model/ObstacleDTO.java | 3 ++ .../api/util/reflect/Initialization.java | 16 +++--- 9 files changed, 87 insertions(+), 49 deletions(-) diff --git a/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/Enemy.java b/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/Enemy.java index cab7493..1d57e55 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/Enemy.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/Enemy.java @@ -1,5 +1,6 @@ package cz.trailsthroughshadows.api.table.enemy.model; +import com.fasterxml.jackson.annotation.JsonInclude; import cz.trailsthroughshadows.api.table.enemy.model.dto.EnemyDTO; import cz.trailsthroughshadows.api.table.schematic.hex.model.dto.HexDTO; import lombok.Data; @@ -8,7 +9,7 @@ @Data @EqualsAndHashCode(callSuper = true) -//@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_NULL) public class Enemy extends EnemyDTO { private HexDTO hex; diff --git a/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/dto/EnemyDTO.java b/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/dto/EnemyDTO.java index a5e79fa..e430f8c 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/dto/EnemyDTO.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/enemy/model/dto/EnemyDTO.java @@ -1,5 +1,6 @@ package cz.trailsthroughshadows.api.table.enemy.model.dto; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import cz.trailsthroughshadows.api.rest.jsonfilter.LazyFieldsFilter; @@ -9,8 +10,7 @@ import cz.trailsthroughshadows.api.util.reflect.Initialization; import jakarta.persistence.*; import jakarta.transaction.Transactional; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import java.util.ArrayList; import java.util.List; @@ -58,10 +58,8 @@ public List getActions() { return actions.stream().map(EnemyActionDTO::getAction).toList(); } - @Transactional - public void loadAll() throws Exception { - Initialization init = new Initialization(); - init.initializeAndUnproxy(this); + public void loadAll() { + Initialization.hibernateInitializeAll(this); } diff --git a/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexEnemyDTO.java b/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexEnemyDTO.java index a6f6908..f3de13e 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexEnemyDTO.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexEnemyDTO.java @@ -1,5 +1,7 @@ package cz.trailsthroughshadows.api.table.schematic.hex.model.dto; +import com.fasterxml.jackson.annotation.JsonInclude; +import cz.trailsthroughshadows.api.rest.jsonfilter.LazyFieldsFilter; import cz.trailsthroughshadows.api.table.enemy.model.dto.EnemyDTO; import jakarta.persistence.*; import lombok.Data; @@ -12,13 +14,14 @@ @Entity @NoArgsConstructor @Table(name = "HexEnemy") +@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = LazyFieldsFilter.class) public class HexEnemyDTO { @EmbeddedId @GeneratedValue(strategy = GenerationType.IDENTITY) private HexEnemyId key; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "idEnemy", insertable = false, updatable = false) private EnemyDTO enemy; diff --git a/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexObstacleDTO.java b/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexObstacleDTO.java index 9737c76..30cc6de 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexObstacleDTO.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/schematic/hex/model/dto/HexObstacleDTO.java @@ -1,5 +1,7 @@ package cz.trailsthroughshadows.api.table.schematic.hex.model.dto; +import com.fasterxml.jackson.annotation.JsonInclude; +import cz.trailsthroughshadows.api.rest.jsonfilter.LazyFieldsFilter; import cz.trailsthroughshadows.api.table.schematic.obstacle.model.ObstacleDTO; import jakarta.persistence.*; import lombok.*; @@ -11,6 +13,7 @@ @AllArgsConstructor @NoArgsConstructor @Table(name = "HexObstacle") +@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = LazyFieldsFilter.class) public class HexObstacleDTO { @EmbeddedId @@ -18,7 +21,7 @@ public class HexObstacleDTO { @Setter(AccessLevel.NONE) private HexObstacleId key; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "idObstacle", insertable = false, updatable = false) private ObstacleDTO obstacle; @@ -27,7 +30,7 @@ public class HexObstacleDTO { public static class HexObstacleId implements Serializable { @Column(nullable = false) - private int idObstacle; + private Integer idObstacle; @Column(nullable = false) private Integer idHex; diff --git a/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/LocationController.java b/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/LocationController.java index 105750f..13637c9 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/LocationController.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/LocationController.java @@ -55,23 +55,24 @@ public ResponseEntity> getLocations( } @GetMapping("/locations/{id}") - public ResponseEntity getLocationById(@PathVariable int id) { + public ResponseEntity getLocationById(@PathVariable int id) { LocationDTO locationDTO = locationRepo .findById(id) .orElseThrow(() -> RestException.of(HttpStatus.NOT_FOUND, "Location with id '%d' not found!", id)); - return new ResponseEntity<>(Location.fromDTO(locationDTO), HttpStatus.OK); + return new ResponseEntity<>(locationDTO, HttpStatus.OK); } @GetMapping("/locations/{locationId}/parts/{partId}") public ResponseEntity getPartByLocationId(@PathVariable int locationId, @PathVariable int partId) { - Part part = Objects.requireNonNull(getLocationById(locationId) - .getBody()) - .getParts() - .stream() - .filter(p -> p.getId() == partId).findFirst() - .orElseThrow(() -> RestException.of(HttpStatus.NOT_FOUND, "Part with id '%d' not found!", partId)); + LocationDTO locationDTO = locationRepo + .findById(locationId) + .orElseThrow(() -> RestException.of(HttpStatus.NOT_FOUND, "Location with id '%d' not found!", locationId)); + Location location = Location.fromDTO(locationDTO); + + Part part = location.getParts().stream().filter(p -> p.getId() == partId).findFirst() + .orElseThrow(() -> RestException.of(HttpStatus.NOT_FOUND, "Part with id '%d' not found!", partId)); return new ResponseEntity<>(part, HttpStatus.OK); } diff --git a/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/Location.java b/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/Location.java index 2e23421..651de05 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/Location.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/Location.java @@ -2,10 +2,15 @@ import com.fasterxml.jackson.annotation.JsonInclude; import cz.trailsthroughshadows.api.table.schematic.location.model.dto.LocationDTO; +import cz.trailsthroughshadows.api.table.schematic.part.model.Part; +import cz.trailsthroughshadows.api.table.schematic.part.model.PartDTO; import lombok.Data; import lombok.EqualsAndHashCode; import org.modelmapper.ModelMapper; +import java.util.ArrayList; +import java.util.List; + @Data @EqualsAndHashCode(callSuper = true) @JsonInclude(JsonInclude.Include.NON_NULL) @@ -14,9 +19,29 @@ public class Location extends LocationDTO { // TODO: Map locations only by specific campaign public static Location fromDTO(LocationDTO dto) { ModelMapper modelMapper = new ModelMapper(); + dto.loadAll(); return modelMapper.map(dto, Location.class); } + @Override + public List getParts() { + if (parts == null) { + return new ArrayList<>(); + } + + return parts.stream() + .map(locationPart -> Part.fromDTO( + locationPart.getPart(), + locationPart.getRotation(), + enemies.stream() + .filter(hexEnemy -> hexEnemy.getKey().getIdPart() == locationPart.getPart().getId()) + .toList(), + obstacles.stream() + .filter(hexObstacle -> hexObstacle.getKey().getIdPart() == locationPart.getPart().getId()) + .toList() + )).toList(); + } + public enum Type { CITY, DUNGEON, MARKET, QUEST } diff --git a/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/dto/LocationDTO.java b/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/dto/LocationDTO.java index 70402fb..61e2742 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/dto/LocationDTO.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/schematic/location/model/dto/LocationDTO.java @@ -7,12 +7,16 @@ import cz.trailsthroughshadows.api.table.schematic.hex.model.dto.HexObstacleDTO; import cz.trailsthroughshadows.api.table.schematic.location.model.Location; import cz.trailsthroughshadows.api.table.schematic.part.model.Part; +import cz.trailsthroughshadows.api.table.schematic.part.model.PartDTO; +import cz.trailsthroughshadows.api.util.reflect.Initialization; import jakarta.persistence.*; import lombok.Data; import lombok.NoArgsConstructor; +import org.modelmapper.ModelMapper; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @Data @Entity @@ -24,55 +28,51 @@ public class LocationDTO { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private int id; + protected int id; @Column(name = "title", nullable = false) - private String title; + protected String title; @Column(name = "tag", length = 32) - private String tag; + protected String tag; @Enumerated(EnumType.STRING) @Column(name = "type", nullable = false) - private Location.Type type; + protected Location.Type type; @Column(name = "description", columnDefinition = "TEXT") - private String description; + protected String description; @OneToMany(mappedBy = "key.idLocation", cascade = CascadeType.ALL, fetch = FetchType.EAGER) - private List parts; + protected List parts; @OneToMany(mappedBy = "idLocation", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List doors; + protected List doors; @OneToMany(mappedBy = "idLocation", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List startHexes; + protected List startHexes; @OneToMany(mappedBy = "idStart", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List paths; + protected List paths; @OneToMany(mappedBy = "key.idLocation", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List enemies; + protected List enemies; @OneToMany(mappedBy = "key.idLocation", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - private List obstacles; + protected List obstacles; public List getParts() { - if (parts == null) { - return new ArrayList<>(); - } - + if (parts == null) return new ArrayList<>(); + ModelMapper modelMapper = new ModelMapper(); return parts.stream() - .map(locationPart -> Part.fromDTO( - locationPart.getPart(), - locationPart.getRotation(), - enemies.stream() - .filter(hexEnemy -> hexEnemy.getKey().getIdPart() == locationPart.getPart().getId()) - .toList(), - obstacles.stream() - .filter(hexObstacle -> hexObstacle.getKey().getIdPart() == locationPart.getPart().getId()) - .toList() - )).toList(); + .map(LocationPartDTO::getPart) + .map(partDTO -> modelMapper.map(partDTO, Part.class)) + .collect(Collectors.toList()); + } + + public void loadAll(){ + Initialization.hibernateInitializeAll(this); } + } diff --git a/src/main/java/cz/trailsthroughshadows/api/table/schematic/obstacle/model/ObstacleDTO.java b/src/main/java/cz/trailsthroughshadows/api/table/schematic/obstacle/model/ObstacleDTO.java index 7281a0a..aac42e0 100644 --- a/src/main/java/cz/trailsthroughshadows/api/table/schematic/obstacle/model/ObstacleDTO.java +++ b/src/main/java/cz/trailsthroughshadows/api/table/schematic/obstacle/model/ObstacleDTO.java @@ -1,5 +1,7 @@ package cz.trailsthroughshadows.api.table.schematic.obstacle.model; +import com.fasterxml.jackson.annotation.JsonInclude; +import cz.trailsthroughshadows.api.rest.jsonfilter.LazyFieldsFilter; import cz.trailsthroughshadows.api.table.effect.Effect; import cz.trailsthroughshadows.api.table.effect.forothers.ObstacleEffect; import jakarta.persistence.*; @@ -13,6 +15,7 @@ @Entity @NoArgsConstructor @Table(name = "Obstacle") +@JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = LazyFieldsFilter.class) public class ObstacleDTO { @Id diff --git a/src/main/java/cz/trailsthroughshadows/api/util/reflect/Initialization.java b/src/main/java/cz/trailsthroughshadows/api/util/reflect/Initialization.java index 2b07b52..62d93f9 100644 --- a/src/main/java/cz/trailsthroughshadows/api/util/reflect/Initialization.java +++ b/src/main/java/cz/trailsthroughshadows/api/util/reflect/Initialization.java @@ -12,12 +12,16 @@ @Log4j2 public class Initialization { - public void initializeAndUnproxy(Object entity) { + /** + * Initializes all fields of the given entity in recursive way. + * @param entity Entity to initialize + */ + public static void hibernateInitializeAll(Object entity) { Map visited = new HashMap<>(); - initializeAndUnproxy(entity, visited); + hibernateInitializeAll(entity, visited); } - private void initializeAndUnproxy(Object entity, Map visited) { + private static void hibernateInitializeAll(Object entity, Map visited) { if (entity == null || visited.containsKey(entity)) { if ((visited.get(entity) > 10)) @@ -42,10 +46,10 @@ private void initializeAndUnproxy(Object entity, Map visited) { Hibernate.initialize(child); if (child instanceof Collection) { for (Object item : (Collection) child) { - initializeAndUnproxy(item, visited); + hibernateInitializeAll(item, visited); } } else { - initializeAndUnproxy(child, visited); + hibernateInitializeAll(child, visited); } } } catch (IllegalAccessException e) { @@ -54,7 +58,7 @@ private void initializeAndUnproxy(Object entity, Map visited) { } } - private boolean isPrimitiveOrWrapper(Class clazz) { + private static boolean isPrimitiveOrWrapper(Class clazz) { return clazz.isPrimitive() || clazz.equals(String.class) || clazz.equals(Integer.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Character.class) || clazz.equals(Byte.class) || clazz.equals(Short.class) || clazz.equals(Boolean.class); }