java - 如何将表与该表的实体类中 View 的一列连接起来

标签 java oracle hibernate jpa spring-data

场景:

  • 我有一个产品表,其中包含以下字段:ID、代码、说明、照片。
  • 我有一个来自其他架构的 Product_stock View ,其中包含以下字段:prod_code、stok_tot

Misson:我需要在 Spring Boot 中做的是将产品与其总库存连接起来。

规则:

  • 我无法在此任务中使用 @Query,我需要在 Product Entity Class 处加入它们,以便 库存成为某种 transient 产品领域。
  • 我无法更改产品 ID 为 Long 且 ProductStock 的 ID 为 String 的事实,但我可以使用产品的代码字段,对吧? (如何?)

到目前为止... 我尝试使用 @OneToOne 和 @JoinColumn 来完成这项工作,但我的 REST 给我的股票字段为 NULL.

“Estoque.java”

@Entity
@Table(name = "VW_ESTOQUE", schema = "ASICAT")
public class Estoque {

    @Id
    @Column(name = "CD_BEM_SERVICO", unique = true, nullable = false)
    private String codigo;

    @Column(name = "ESTOQUE")
    private Long estoque;

    // getters and setters hidden by me
}

“产品.java”

@Entity
@NamedEntityGraph(name = "Produto.detail", attributeNodes = @NamedAttributeNode("categorias"))
public class Produto implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Long id;

    private String codigo;

    private String descricao;

    // here is where I get the null values
    @Transient
    @OneToOne(fetch = FetchType.LAZY)
    @JoinTable(name = "VW_ESTOQUE", joinColumns = @JoinColumn(name = "CODIGO", referencedColumnName = "CODIGO"), inverseJoinColumns = @JoinColumn(name = "CD_BEM_SERVICO", referencedColumnName = "CODIGO"))
    private Estoque estoque;

    private String hash;

    @ManyToMany(mappedBy = "produtos", fetch = FetchType.EAGER)
    @BatchSize(size = 10)
    private List<Categoria> categorias = new ArrayList<>();

    // getters and setters hidden by me

}

在我的产品存储库中,我调用 FindAll()

最佳答案

您已注释Produto.estoque@Transient ,这意味着它不是实体持久状态的一部分。当管理该实体的实例时,这样的字段既不会被写入也不会被读取。这不会达到你的目的。

我可以想象您可能一直在努力实现两件事:

  1. 每次 Estoque通过 Produto 访问,应该从DB加载以保证其新鲜度。 JPA 没有提供这一点,尽管您可能想要注释 Estoque@Cacheable(value = false) ,并在 Produto 上指定延迟获取策略。关系的另一面。

  2. 您希望避免持久性提供程序尝试持久保存对 Estoque 的任何更改。 ,因为它由 View 支持,而不是可更新的表。 这个我们可以解决。

我的第一个建议是映射 ASICAT.VW_ESTOQUE作为辅助表而不是完全独立的实体。这可能看起来像这样:

@Entity
@SecondaryTable(name = "VW_ESTOQUE", schema = "ASICAT"
        pkJoinColumns = {
            @PrimaryKeyJoinColumn(name = "CD_BEM_SERVICO",
                    referencedColumnName = "CODIGO") })
public class Produto implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Long id;

    private String codigo;

    private String descricao;

    @Column(name = "ESTOQUE", table = "VW_ESTOQUE", nullable = true,
            insertable = false, updatable = false)
    private Long estoque;

    // ...
}

您还可以避免为 estoque 提供 setter属性。

但是SecondaryTable如果您不能依赖ESTOQUE,该方法可能无法正常工作。 View 始终为 PRODUTO 的每一行提供一行,因为检索中很可能涉及内部联接。此外,您不会以这种方式进行惰性获取。主要的替代方案或多或少是您在问题中提出的内容:设置一个单独的 Estoque实体。

如果您确实设置了单独的 Estoque ,但是,那么我会采取不同的方法。具体来说,

  • 我会将这种关系设为双向,这样我就可以
  • 制作Estoque实体关系所有者。

然后是这样的:

@Entity
public class Produto implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    private Long id;

    private String codigo;

    private String descricao;

    // must not be @Transient:
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "produto", cascade = {
            CascadeType.REFRESH
        })
    private Estoque estoque;

    // ...    
}

@Entity
@Table(name = "VW_ESTOQUE", schema = "ASICAT")
@Cacheable(value = false)
public class Estoque {

    @Id
    @Column(name = "CD_BEM_SERVICO", nullable = false,
            insertable = false, updatable = false)
    private String codigo;

    @Column(name = "ESTOQUE", insertable = false, updatable = false)
    private Long estoque;

    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "CD_BEM_SERVICO", referencedColumnName = "CODIGO",
        nullable = false, insertable = false, updatable = false, unique = true)
    Produto produto;

    // getters and setters hidden by me
}

在这种情况下,我会避免为 Estoque 的任何属性提供 setter 方法。 ,并避免提供任何允许设置初始属性值的构造函数。因此,对于第一个近似值,唯一的 实例的属性将采用非空值的方式是它们是由持久性提供程序设置的。

此外,既然您提到了 Oracle,如果您使用 TopLink 作为持久性提供程序,那么您可能会考虑应用其 @ReadOnly扩展属性为Estoque实体,代替或什至补充其中一些防止尝试插入或更新 View 的保护。

关于java - 如何将表与该表的实体类中 View 的一列连接起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48465574/

相关文章:

java - Hibernate - 如何映射表示集合的对象

java - 使用 Java 清理 CSS

java - 在java中按句号和引号分割字符串

java - 为什么 Spring 的 @Transactional 有助于性能

java - spring中sql查询失败如何回滚事务

oracle - 我需要授予访问权限以在另一个模式中使用一个模式的表

java - 如何在 Java 中移动球

java - 常识问题 : Network Access Time, 缓存访问时间、磁盘访问时间

sql - 在 Oracle 数据库中设置一个数字的特定位

sql-server - Objective-C:数据库支持