Tengo un problema extraño, en el que estoy luchando por comprender la naturaleza del "contexto estático" en Java, a pesar de las numerosas preguntas de SO sobre el tema.
TL;RD:
Tengo un defecto de diseño, donde...
Esto funciona:
List<OrderExtnTrans> list = orderType.getOrderExtnTransList(); this.dtoOrderExtnTransList = list.stream().map(OrderExtnTrans::toDto).collect(Collectors.toList());Pero esto no:
this.dtoOrderExtnTransList = orderType.getOrderExtnTransList().stream().map(OrderExtnTrans::toDto).collect(Collectors.toList());
El error que se muestra en la segunda versión es "No se puede hacer referencia al método no estático desde un contexto estático".
La versión larga:
Modelo de objeto: el modelo consta de órdenes específicas de tipo comercial (por ejemplo, bolsa de valores, pagos), que se heredan de una entidad de orden a través de una estrategia de herencia "InheritanceType.JOINED". El pedido principal se puede parametrizar con el objeto DTO específico del tipo de negocio de ese pedido, por ejemplo, DtoStockExchangeOrder. Esto es para permitir que los objetos JPA se puedan asignar a su equivalente DTO dentro de la Entidad, en lugar de en un servicio (lo que hice anteriormente. Funcionó, pero es "menos limpio").
Orden JPA:
@Entity @Table(name = "ORDER_BASE") @Inheritance(strategy = InheritanceType.JOINED) public class Order<DtoOrderType extends DtoOrder> implements Serializable { @OneToMany(fetch = FetchType.LAZY, mappedBy = "order", orphanRemoval = true) private List<OrderExtnTrans> orderExtnTransList = new ArrayList<>(); }Orden JPA - Ejemplo específico del tipo de negocio:
@Entity @Table(name = "ORDER_STEX") @Inheritance(strategy = InheritanceType.JOINED) public class OrderStex extends Order<DtoOrderStex> implements Serializable {Del mismo modo, las órdenes DTO siguen el mismo patrón, donde pueden parametrizarse con la entidad JPA específica del tipo de negocio, para habilitar el mapeo relevante:
Orden DTO:
public class DtoOrder<OrderType extends Order> extends DtoEntity {Orden DTO - Ejemplo específico del tipo de negocio
public class DtoOrderStex extends DtoOrder<OrderStex> {La clase DTOEntity de la que hereda es solo una clase "envoltura", que consta de una identificación y un nombre.
Ahora la parte complicada: la clase DTOOrder tiene un constructor que completa los campos que son comunes a todos los tipos de negocios, como la lista de transiciones de estado del proceso, por las que pasa un pedido en su ciclo de vida (colocado, cancelado, ejecutado, etc.) . Siguiendo con el ejemplo de las transiciones de estado del proceso, estas también se modelan como entidades JPA en la base de datos, con sus correspondientes contrapartes DTO (igualmente parametrizadas, esa parte funciona bien).
Aquí el constructor:
public DtoOrder(OrderType orderType) { super(orderType); // this is the part from above, which works (but it shows a warning: Unchecked assignment: 'java.util.List' to 'java.util.List<com.tradingvessel.core.persistence.model.OrderExtnTrans>' ) List<OrderExtnTrans> list = orderType.getOrderExtnTransList(); this.dtoOrderExtnTransList = list.stream().map(OrderExtnTrans::toDto).collect(Collectors.toList()); // this is how I would have expected it to work, but it does not, with the error shown above: "Non-static method cannot be referenced from a static context" this.dtoOrderExtnTransList = orderType.getOrderExtnTransList().stream().map(OrderExtnTrans::toDto).collect(Collectors.toList()); }Si comento la versión que no funciona, la aplicación se comporta como se esperaba y no arroja ningún error, por lo que "lógicamente", esto funciona. Pero JAVA no lo permite como se desarrolló en la segunda versión.
Si en lugar de OrderType uso "Orden", también funciona, pero obviamente arroja errores en otros lugares, porque la firma del constructor cambió. Supongo que otro enfoque sería parametrizar el método en función de la persona que llama al constructor o parametrizar la clase principal DtoOrder para conocer el tipo de la clase secundaria, pero ¿debería haber una mejor manera?
¿Qué estoy haciendo mal y por qué la versión superior funciona como se esperaba?
Una forma de resolver el problema es parametrizar la clase ParentDTO con sus propios hijos.
public class DtoOrderStex extends DtoOrder<OrderStex, DtoOrderStex> { public DtoOrderStex(OrderStex orderStex) { super(orderStex); } public DtoOrderStex() { } }Esto plantea la pregunta: ¿Tiene esto efectos secundarios negativos graves, además de la redundancia en las clases de niños? ¿Y por qué es eso necesario en primer lugar, dado que la clase ya es hija de su padre?