我想使用資料庫中的本機查詢來檢索給定記錄的更多資料,并且我正在尋找有關如何宣告容納此資料的欄位的解決方案。
如果我不注釋該欄位,則在更新期間 JPA 認為該欄位應映射到具有相同名稱的列(表中當然不存在);如果我用 注釋它@Transient,該欄位在更新時被忽略,但在選擇時也被忽略(為什么?)。
讓我們用一個例子來澄清一下。我有物體Discount
class Discount {
@Column(name = "ID")
private long id;
@Column(name = "PRODUCT_ID")
private long productId;
// private String productName; <-- Uncommented, error on save; with @Transient empty on read
}
當我從資料庫中檢索折扣時,我還想使用相同的查詢來回傳整個記錄以及來自Product表的產品名稱。
使用 Spring 存盤庫,我將查詢設定如下:
public interface DiscountRepo extends Repository<Discount, Long> {
@Query(nativeQuery = true, value = "select d.*,p.name as productName from discount d join product p on d.product_id = d.id")
List<Discount> getAll();
}
我不想private Product product在Discount物體中擁有像這樣的屬性的原因是,在選擇時會從資料庫中傳輸太多資料,而我只需要產品名稱。
uj5u.com熱心網友回復:
使用@Transient 標記欄位與為Java 序列化程序標記瞬態具有相同的效果——它完全被排除在兩個方向的資料庫持久性之外。無論如何,您都不希望嘗試將其作為常規屬性讀入,因為這會干擾所有 Discount 讀取操作 - 如果這是您想要的,您可能應該在物體中映射此欄位。
我建議您為此資料操作使用其他一些非物體物件,這樣您的業務邏輯就不會混淆或混合此 Discount 物件資料與額外的“productName”被填充到 Discount 上的其他 JPA 操作,它將留在哪里出去。
也就是說,您可以使用 JPA 建構式查詢或建構式操作讓它從資料中構建任何 pojo。您所需要的只是物件上的建構式以接收相同的引數和型別。
@Entity
class Discount {
@Column(name = "ID")
private long id;
@Column(name = "PRODUCT_ID")
private long productId;
@Transient
private String productName;
public AbstractDomainObject(Long id, Long productId, String productName) {
this.id = id;
this.productId = productId;
this.productName = productName;
}
}
然后你可以使用
public interface DiscountRepo extends Repository<Discount, Long> {
@Query("select new your.package.Discount(d.id, d.productId, p.productName) from discount d join product p on d.productId = p.id"
List<Discount> getAll();
}
如果您的提供商不支持這樣的加入(有些允許),您仍然可以獲得產品參考折扣。只需確保將其標記為惰性 - 在查詢中使用它不會強制獲取所有資料。只要確保你的提供者支持惰性關系,因為許多需要額外的東西,比如增強,類:
public interface DiscountRepo extends Repository<Discount, Long> {
@Query("select new your.package.Discount(d.id, d.productId, p.productName) from discount d join d.product p"
List<Discount> getAll();
}
或者您仍然可以使用本機查詢,但可能希望使用定義結果構建方式的 SqlResultSetMapping 在您的物體中定義它:
@Entity
@SqlResultSetMappings(
SqlResultSetMapping(
name = "summary",
classes = [
ConstructorResult(
targetClass = Discount.class,
columns = [
ColumnResult(name = "id", type = Long::class),
ColumnResult(name = "productId", type = Long::class),
ColumnResult(name = "productName", type = String::class)
]
)
]
)
)
@NamedNativeQueries(
NamedNativeQuery(name = "Discount.getAll",
query = "select d.*,p.name as productName from discount d join product p on d.product_id = p.id", resultSetMapping = "summary")
)
class Discount {
..
然后 Spring 應該在你的 repo 中執行 getAll 時查找該查詢名稱:
public interface DiscountRepo extends Repository<Discount, Long> {
List<Discount> getAll();
}
uj5u.com熱心網友回復:
您可以使用JdbcTempate然后將回傳值映射到Discount.class
String sqlQuery = "select d.ID as id , d.PRODUCT_ID as productId p.name as productName from discount d join product p on d.product_id = d.id";Map<String, Object> result = jdbcTemplate.queryForMap(sqlQuery);Discount discount = new ObjectMapper().convertValue(result, Discount.class);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/435816.html
上一篇:如何在底部導航欄androidstudio上設定默認選擇
下一篇:如何使用指標將陣列傳遞給函式
