Java 如何将表与该表中视图的一列联接';s实体类
场景:Java 如何将表与该表中视图的一列联接';s实体类,java,oracle,hibernate,jpa,spring-data,Java,Oracle,Hibernate,Jpa,Spring Data,场景: 我有一个包含以下字段的products表:id、代码、描述、照片 我有一个来自其他模式的product_stock视图,其中包含字段:prod_code,stok_tot 米森:在Spring Boot中,我需要做的是将这些产品与它们的总库存结合起来 规则: 我不能在这个任务中使用@Query,我需要在产品实体类中加入它们,这样库存就变成了某种产品的临时字段 我不能改变这样一个事实,即产品的ID是一个长的,ProductStock的ID是一个字符串,但我可以使用产品的代码字段,对吗
- 我有一个包含以下字段的products表:id、代码、描述、照片
- 我有一个来自其他模式的product_stock视图,其中包含字段:prod_code,stok_tot
Spring Boot
中,我需要做的是将这些产品与它们的总库存结合起来
规则:
- 我不能在这个任务中使用
,我需要在产品@Query
中加入它们,这样实体类
就变成了某种产品的临时字段库存
- 我不能改变这样一个事实,即产品的ID是一个
,ProductStock的ID是一个长的
,但我可以使用产品的代码字段,对吗?(怎么做?)字符串
REST
将stock字段设置为NULL
“Estoque.java”
“Produto.java”
@实体
@NamedEntityGraph(name=“Produto.detail”,attributeNodes=@NamedAttributeNode(“categorias”))
公共类Produto实现了可序列化{
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE)
私人长id;
私有字符串codigo;
私有字符串描述符;
//这里是我得到空值的地方
@短暂的
@OneToOne(fetch=FetchType.LAZY)
@JoinTable(name=“VW_ESTOQUE”、joinColumns=@JoinColumn(name=“CODIGO”、ReferenceColumnName=“CODIGO”)、inverseJoinColumns=@JoinColumn(name=“CD_BEM_SERVICO”、ReferenceColumnName=“CODIGO”))
私人爱沙尼亚语;
私有字符串散列;
@ManyToMany(mappedBy=“produtos”,fetch=FetchType.EAGER)
@批量大小(大小=10)
私有列表categorias=new ArrayList();
//被我藏起来的能手和二传手
}
在我的产品存储库中,我调用FindAll()您已经将
Produto.estoque
注释为@Transient
,这意味着它不是实体持久状态的一部分。当管理该实体的实例时,这样的字段既不会被写入也不会被读取。那不符合你的目的
有两件事我可以想象你可能一直在努力实现:
Produto
访问Estoque
时,都应从数据库加载,以确保其新鲜度。JPA没有提供这种功能,尽管您可能希望使用@Cacheable(value=false)
注释Estoque
,并在关系的Produto
端指定延迟获取策略Estoque
的任何更改,因为它是由视图支持的,而不是由可更新的表支持的。我们可以解决这个问题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
但是如果不能始终依靠ESTOQUE
视图为PRODUTO
的每一行提供一行,那么SecondaryTable
方法可能无法很好地工作,因为在检索过程中很可能会涉及到内部联接。此外,您不会以这种方式获得懒惰的抓取。主要的替代方案或多或少是您在问题中提出的内容:设置一个单独的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方法,并避免提供任何允许设置初始属性值的构造函数。因此,在一级近似下
实例属性采用非null值的方式是,如果它们是由持久性提供程序设置的
此外,由于您提到了Oracle,如果您使用TopLink作为持久性提供程序,那么您可能会考虑将其<代码> @ RealOnt< /Cord>扩展属性应用到<代码> Estoque <代码>实体中,代替或甚至添加一些保护措施,以避免插入或更新视图。我将在周一测试这两种方法。我将使用有效的方法。无论如何,我不需要Estoque成为一个实体,更不用说懒惰了。在第一个示例中:SecondaryTable JoinColumn不能引用非主键
@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;
// ...
}
@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
}