簡體   English   中英

Spring Hibernate查詢與非主鍵的一對一關系

[英]Spring Hibernate Query One to One relationship with non primary key

我正在使用 Hibernate 在 Spring 上開發 Web 應用程序。

此 Web 應用程序基本上是一個在線商業網站,其中包含特定類別下的許多產品。

本應用支持一個產品多種語言,單個產品圖片支持不同尺寸的圖片,以便根據不同的用戶設備進行優化。 因此,用戶可以根據自己的設備類型(例如移動設備、iPad、桌面設備)選擇他們希望使用的語言來查看產品描述,並會獲得不同尺寸的產品圖像。

所以,我現在有六個表,如下所示。

在此處輸入圖片說明

產品表包含如圖所示的產品

在此處輸入圖片說明

product_info 表包含不同語言的產品(如英語、西班牙語和韓語)的相同描述,如下圖所示。

在此處輸入圖片說明

product_image 包含產品相同圖片的不同尺寸圖像的相對路徑,如下圖所示。

在此處輸入圖片說明

假設用戶請求 category_id = 1(家具)、support_language_id = 1(英語)和 device_type_id = 1(移動)下的產品列表。 然后,我想查詢如下內容,但使用 HQL。

Select * from product pr
left join product_info pf
on p.id = pf.product_id
left join product_image pi
on p.id = pi.product_id
where category_id = category_id of user choice
and support_language_id = support_language_id of user choice
and device_type_id = device_type_id of user device

當我執行這個 HQL 查詢時,我希望得到一個產品對象列表,每個產品對象只有一個 product_info 對象和一個 product_image 對象,基於用戶選擇的 category_id、support_language_id 和 device_type_id。

按照上面的例子,我將得到一個 id = 1 的產品對象,因為只有一個 category_id = 1 的對象。然后,products 對象將有 id = 1 的 product_info 對象和 id = 1 的 product_image 對象。

如何使用 Hibernate 在 JPA 中實現這種關系?

我已經嘗試過這種方式,但最終會出現錯誤,例如與非主鍵或其他鍵綁定。 所以我首先想知道我的數據庫設計是否存在結構問題。

你們能給我提供一個完整的工作代碼示例,其中包含所有這些 JPA 注釋,例如 @JoinColumn、@OneToMany、@OneToOne 等等,好嗎?

只要可以獲得所需的結果,您就可以更改、添加和刪除列或表。

這里有一個不使用注解,只使用hql的解決方案,不知道能不能滿足你。

select p from Product p,ProductInfo pf,ProductImage pi where p.id = pf.productId and p.id = pi.productId and...

很簡單,假設您沒有 10 年前的 JPA 版本,那么您可以創建兩個接口(在本例中為存儲庫)並按照 JPA 命名約定命名方法。 這意味着,如果您定義了一個 ProductInfo 類:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductInfo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "product_info_id")
    private long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "product_id")
    private Product product;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "language_id")
    private Language language;

    private String description;

}

這將是您需要的相應 Repository 方法,是的,如果您想讓它干凈和簡單,您將需要傳遞整個產品。

 @Repository
 public interface ProductImageRepository extends JpaRepository<ProductImage, Long> {

    public Optional<ProductImage> findByProductAndDevice(Product product, Device device);

}

ProductImage 也是如此

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductImage {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "product_image_id")
    private long id;

    @ManyToOne
    @JoinColumn(name = "product_id")
    private Product product;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "device_id")
    private Device device;

    private String image;

}

誰的存儲庫方法將是

@Repository
public interface ProductImageRepository extends JpaRepository<ProductImage, Long> {

    public Optional<ProductImage> findByProductAndDevice(Product product, Device device);

}

然后你會想要一些包含產品信息的東西

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductToDisplay {

    private Product product;
    private String description;
    private String imageLocation;
}

然后根據您擁有的信息創建該對象的服務

@Service
public class ProductToDisplayService {

    @Autowired
    private ProductInfoRepository productInfoRepository;
    @Autowired
    private ProductImageRepository productImageRepository;

    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private DeviceRepository deviceRepository;
    @Autowired
    private LanguageRepository languageRepository;

    public ProductToDisplay getProduct(long productID, long languageID, long deviceID) throws Exception {
        Product product =
                productRepository.findById(productID).orElseThrow(()-> new Exception(
                        "There is no such product"));

        return new ProductToDisplay(product,
                productInfoRepository.findByProductAndLanguage(product,
                        languageRepository.findById(languageID).orElseThrow(()-> new Exception(
                                "There is no such product"))).orElseThrow(()-> new Exception(
                        "There is no such product info")).getDescription(),
                productImageRepository.findByProductAndDevice(product,
                        deviceRepository.findById(deviceID).orElseThrow(()-> new Exception(
                                "There is no such product"))).orElseThrow(()-> new Exception(
                        "There is no such product Image")).getImage());
    }
}

這可能看起來有點令人困惑,對此我很抱歉,但這更清楚一點

public ProductToDisplay getProductClear(long productID, long languageID,
                                     long deviceID) throws Exception {
    Product product =
            productRepository.findById(productID).orElseThrow(()-> new Exception(
                    "There is no such product"));

    Language language = languageRepository.findById(languageID).orElseThrow(()-> new Exception(
            "There is no such language"));
    ProductInfo prodInfo = productInfoRepository.findByProductAndLanguage(product, language)
            .orElseThrow(()-> new Exception(
            "There is no such product info"));

    Device device =  deviceRepository.findById(deviceID).orElseThrow(()-> new Exception(
            "There is no such image"));
    ProductImage prodImg = productImageRepository.findByProductAndDevice(product, device)
            .orElseThrow(()-> new Exception(
            "There is no such product Image"));

    return new ProductToDisplay(product,
            prodInfo.getDescription(), prodImg.getImage());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM