Получить данные столбца из отношения «один ко многим» в данных JPA Spring - PullRequest
0 голосов
/ 25 сентября 2019

Предположим, у меня есть две таблицы базы данных, Product и ProductDetails.

create table Product
{
    product_id int not null,
    product_name varchar(100) not null,
    PRIMARY KEY (product_id)
}
create table ProductDetails
{
    detail_id int not null,
    product_id int not null,
    description varchar(100) not null,
    PRIMARY KEY (detail_id,product_id),
    FOREIGN KEY (product_id) REFERENCES Product(product_id)
}

Каждый продукт может иметь несколько записей сведений о продукте, но каждая деталь продукта может принадлежать только одному продукту.В SQL я хочу иметь возможность получать информацию о каждом продукте, но также и с именем продукта, и я сделал бы это с помощью оператора соединения.

select p.product_id,pd.detail_id,p.product_name,pd.description
from Product p join ProductDetails pd on p.product_id=pd.product_id

Теперь мне нужно иметь эту концепцию в данных SpringJPA форма.В настоящее время я понимаю следующее:

@Table(name = "Product")
public class ProductClass
{
    private int productID;
    private String productName;
}

@Table(name = "ProductDetails")
public class ProductDetailsClass
{
    private int detailID;
    private int productID;

    // this is the part I don't know how to set. @OneToMany? @ManyToOne? @JoinTable? @JoinColumn?
    private String productName;

    private String description;
}

(я не включал никаких атрибутов, таких как @Id, чтобы код оставался минимальным)

Что мне нужно написать, чтобы получить этоprivate String productName; работает?Мои исследования @JoinTable и @OneToMany и других атрибутов просто смущают меня больше.

PS Это унаследованная унаследованная Java-программа.Часть private String productName; не была в исходном коде, но теперь мне нужно, чтобы класс ProductDetails имел в наличии productName.

PPS Я хочу иметь четкое понимание того, что я делаю, прежде чем пытатьсячто угодно и развертывание.Это устаревшая программа, развернутая в рабочей среде, и, насколько я понимаю, любые изменения кода здесь также могут изменить структуру базы данных, и никаких денег не достаточно, чтобы заставить меня захотеть восстановить Java-программу, Spring Framework, Apache.сервер и база данных MySQL в рабочем состоянии, если происходит что-то катастрофическое.Кроме того, у меня действительно нет среды разработки, чтобы проверить это.Помощь ...

1 Ответ

0 голосов
/ 25 сентября 2019

Ваше исследование уже идет в правильном направлении: вам понадобятся @OneToMany отношения.Лучшие описания для Hibernate имеет Влад Михалча .На его веб-странице вы также можете найти хорошее объяснение этих отношений: Лучший способ отобразить отношения @OneToMany с JPA и Hibernate .

Во-первых, вам нужно будет правильно создать объекты(сущность представлена ​​таблицей в реляционной базе данных).

Однонаправленный (@OneToMany)

@Entity
@Table(name = "product")
public class Product
{
    @Id
    @GeneratedValue
    private Long productID;

    private String productName;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ProductDetail> productDetails;

    //Constructors, getters and setters...
}

@Entity
@Table(name = "product_details")
public class ProductDetail
{
    @Id
    @GeneratedValue
    private Long detailID;

    private String description;

    //Constructors, getters and setters...
}

Это основано на однонаправленном отношении.Следовательно, каждый Продукт знает все выделенные ProductDetails.Но ProductDetails не имеют ссылки на свои продукты.

Однонаправленный (@ManyToOne)

@Entity
@Table(name = "product")
public class Product
{
    @Id
    @GeneratedValue
    private Long productID;

    private String productName;

    //Constructors, getters and setters...
}

@Entity
@Table(name = "product_details")
public class ProductDetail
{
    @Id
    @GeneratedValue
    private Long detailID;

    private String description;

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

    //Constructors, getters and setters...
}

В этом однонаправленном отношении только ProductDetails знает, какой Продукт назначен им.Учтите это для огромного количества объектов ProductDetail для каждого Product.

Аннотация @JoinColumn указывает имя столбца таблицы product_details, в которой сохраняется внешний ключ для Product (его идентификатор).Он также работает без, но с этой аннотацией он более эффективен.

Двунаправленный (@OneToMany и @ManyToOne)

@Entity
@Table(name = "product")
public class Product
{
    @Id
    @GeneratedValue
    private Long productID;

    private String productName;

    @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<ProductDetail> productDetails;

    //Constructors, add, remove method, getters and setters...
}

@Entity
@Table(name = "product_details")
public class ProductDetail
{
    @Id
    @GeneratedValue
    private Long detailID;

    private String description;

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

    //Constructors, getters and setters...
}

С двунаправленными объектами отношений обеих сторон (Product и ProductDetail) известнокакие другие объекты были им присвоены.

Но, по словам Влада Михалча, это не следует использовать, если существует слишком много ProductDetails для каждого продукта .

Также не забывайте реализовывать правильноедобавить и удалить методы для записей в списке (см. article снова, в противном случае странные исключения ).

Разное

При каскадных изменениях в Productтакже применяются к его ProductDetails.OrphanRemoval избегает использования ProductDetails без Product.

Product product = new Product("Interesting Product");

product.getProductDetails().add(
    new ProductDetails("Funny description")
);
product.getProductDetails().add(
    new ProductDetails("Different description")
);

entityManager.persist(product);

Часто вопрос о правильных методах equals и hashCode является сложной головоломкой в ​​вашей голове.Специально для двунаправленных отношений, но также и в других ситуациях, использующих соединение с базой данных, рекомендуется реализовать их довольно просто, как описано Владом .

Хорошей практикой является использование объектов для примитивных типов данных.также.Это дает вам возможность получить правильное значение NULL при вызове метода получения.

Избегать энергичной выборки должно быть совершенно ясно ...

Когда вы сейчас пытаетесь получитьProduct вне базы данных, объект автоматически получает список всех назначенных ему ProductDetails.Для этого можно использовать JPA репозитории в Spring .Простые методы не должны быть реализованы.Если вам нужно больше настраивать функциональность, взгляните на эту статью Baeldung .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...