I have this (one-to-many) relationships Fleet
-> Configuration
-> Software
and I'm interested to get all Configurations
(with one Fleet
and all Software
). The problem is that Micronaut do not want to load systems.
Note:
@Join
and @JoinSpecifications
but it didn't workedMy classes:
@javax.persistence.Entity
@MappedEntity
@NoArgsConstructor
@Data
@Builder
public class Configuration {
@Id
@GeneratedValue(GeneratedValue.Type.AUTO)
private Long id;
// other fields
@NotNull
@ManyToOne(optional = false)
@JoinColumn(nullable = false, updatable = false)
private Fleet fleet;
@NotNull
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@Relation(value = Relation.Kind.ONE_TO_MANY)
private List<Software> softwares;
}
@javax.persistence.Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Fleet {
@Id
@GeneratedValue(GeneratedValue.Type.AUTO)
private Long id;
@NotNull
@Size(min = 1, max = 255)
@Column(unique = true)
private String name;
// no mapping to Configuration - I'm not interested in it
}
@MappedEntity
@javax.persistence.Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class Software implements Entity {
@Id
@GeneratedValue(GeneratedValue.Type.AUTO)
private Long id;
// other fields
@NotNull
@ManyToOne(optional = false)
@JoinColumn(nullable = false, updatable = false)
@Relation(value = Relation.Kind.MANY_TO_ONE)
@ToString.Exclude
private Configuration configuration;
}
@JdbcRepository(dialect = Dialect.H2)
@JoinSpecifications(
{
@Join(value = "softwares", type = Join.Type.LEFT_FETCH),
@Join(value = "fleet", type = Join.Type.LEFT_FETCH)
}
)
public interface ConfigurationRepository extends ReactorPageableRepository<Configuration, Long> {}
SELECT configuration_.`id`,
configuration_.`name`,
configuration_.`project_name`,
configuration_.`version_w`,
configuration_.`version_x`,
configuration_.`version_y`,
configuration_.`version_z`,
configuration_.`version_description`,
configuration_.`approved_date`,
configuration_.`imported_date`,
configuration_.`fleet_id`,
configuration_softwares_.`id` AS softwares_id,
configuration_softwares_.`name` AS softwares_name,
configuration_softwares_.`supplier` AS softwares_supplier,
configuration_softwares_.`description` AS softwares_description,
configuration_softwares_.`circuit_diagram` AS softwares_circuit_diagram,
configuration_softwares_.`comment` AS softwares_comment,
configuration_softwares_.`date` AS softwares_date,
configuration_softwares_.`version_w` AS softwares_version_w,
configuration_softwares_.`version_x` AS softwares_version_x,
configuration_softwares_.`version_y` AS softwares_version_y,
configuration_softwares_.`version_z` AS softwares_version_z,
configuration_softwares_.`version_description` AS softwares_version_description,
configuration_softwares_.`checksum_cipher` AS softwares_checksum_cipher,
configuration_softwares_.`checksum_hash` AS softwares_checksum_hash,
configuration_softwares_.`system_id` AS softwares_system_id,
configuration_softwares_.`configuration_id` AS softwares_configuration_id,
configuration_fleet_.`name` AS fleet_name
FROM `configuration` configuration_
LEFT JOIN `fleet` configuration_fleet_
ON configuration_.`fleet_id` = configuration_fleet_.`id`
INNER JOIN `configuration_software` configuration_softwares_configuration_software_
ON configuration_.`id` =
configuration_softwares_configuration_software_.`configuration_id`
INNER JOIN `software` configuration_softwares_
ON configuration_softwares_configuration_software_.`software_id` =
configuration_softwares_.`id`
ORDER BY configuration_.name ASC, configuration_.approved_date ASC, configuration_.imported_date ASC
To start off with you are mixing JPA and Micronaut Data annotations.
@javax.persistence.Entity
@MappedEntity
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@Relation(value = Relation.Kind.ONE_TO_MANY)
Which might be possible, haven't tried. But based on your ConfigurationRepository
you should be using the Micronaut Data annotations, see the guide on "Access a database with Micronaut Data R2DBC".
Below is a simple non-reactive version of your code:
import io.micronaut.data.annotation.GeneratedValue;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;
@MappedEntity
public class Fleet {
@Id
@GeneratedValue
private Long id;
private String name;
... getter and setters...
}
import io.micronaut.core.annotation.Nullable;
import io.micronaut.data.annotation.GeneratedValue;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;
import io.micronaut.data.annotation.Relation;
@MappedEntity
public class Software {
@Id
@GeneratedValue
private Long id;
private String version;
@Relation(Relation.Kind.MANY_TO_ONE)
private Configuration configurations;
... getter and setters...
}
import io.micronaut.core.annotation.Nullable;
import io.micronaut.data.annotation.GeneratedValue;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;
import io.micronaut.data.annotation.Relation;
@MappedEntity
public class Configuration {
@Id
@GeneratedValue
private Long id;
@Relation(value = Relation.Kind.MANY_TO_ONE, cascade = Relation.Cascade.ALL)
private Fleet fleet;
@Nullable
@Relation(value = Relation.Kind.ONE_TO_MANY, cascade = Relation.Cascade.ALL)
private List<Software> softwares;
... getter and setters...
}
@JdbcRepository(dialect = Dialect.POSTGRES)
@JoinSpecifications(
{
@Join(value = "softwares", type = Join.Type.LEFT_FETCH),
@Join(value = "fleet", type = Join.Type.LEFT_FETCH)
}
)
//-- or ---
//@Join(value = "fleet", type = Join.Type.LEFT_FETCH)
//@Join(value = "softwares", type = Join.Type.LEFT_FETCH)
public interface ConfigurationRepository extends CrudRepository<Configuration, Long> {
}
Micronaut Data documentation