В двунаправленной ассоциации JPA OneToMany/ManyToOne что подразумевается под "обратной стороной ассоциации"?
в этих примерах на ссылка на аннотацию TopLink JPA:
Пример 1-59 @OneToMany - Класс Клиента С Дженериками
@Entity
public class Customer implements Serializable {
...
@OneToMany(cascade=ALL, mappedBy="customer")
public Set<Order> getOrders() {
return orders;
}
...
}
Пример 1-60 @ManyToOne-Класс Порядка С Дженериками
@Entity
public class Order implements Serializable {
...
@ManyToOne
@JoinColumn(name="CUST_ID", nullable=false)
public Customer getCustomer() {
return customer;
}
...
}
мне кажется, что Customer
субъект является владельцем ассоциации. Однако, в объяснении для mappedBy
атрибут в том же документе написано, что:
если связь является двунаправленной,
затем установите элемент mappedBy на
обратная (не владеющая) сторона
связь с именем Поля
или свойство, которое владеет отношением
как показывает пример 1-60.
однако, если я не ошибаюсь, это выглядит как в Примере mappedBy
фактически указывается на стороне владельца ассоциации, а не на стороне не владельца.
так что мой вопрос в принципе:
в двунаправленная (один ко многим/много к одному) ассоциация, которая из сущностей является владельцем? Как мы можем обозначить одну сторону как владельца? Как мы можем обозначить много сторон в качестве владельца?
Что подразумевается под "обратной стороны Ассоциации"? Как мы можем обозначить одну сторону как обратную? Как мы можем обозначить многие стороны как обратные?
5 ответов:
чтобы понять это, вы должны сделать шаг назад. В OO заказчику принадлежат заказы (заказы-это список в объекте customer). Не может быть заказа без клиента. Таким образом, клиент, похоже, является владельцем заказов.
но в мире SQL один элемент фактически будет содержать указатель на другой. Поскольку существует 1 клиент для N заказов, каждый заказ содержит внешний ключ для клиента, которому он принадлежит. Это "соединение", и это означает, что заказ "владеет" (или буквально содержит) связь (информацию). Это в точности противоположно миру ОО / модели.
Это может помочь понять:
public class Customer { // This field doesn't exist in the database // It is simulated with a SQL query // "OO speak": Customer owns the orders private List<Order> orders; } public class Order { // This field actually exists in the DB // In a purely OO model, we could omit it // "DB speak": Order contains a foreign key to customer private Customer customer; }
обратной стороной является ОО "владелец" объекта, в данном случае заказчик. У клиента нет столбцов в таблице для хранения заказов, поэтому вы должны сказать ему, где в таблице заказов он может сохранить эти данные (что происходит через
mappedBy
).
Невероятно, но за 3 года никто не ответил на ваш отличный вопрос с примерами обоих способов отображения отношений.
Как упоминалось другими, сторона" владелец " содержит указатель (внешний ключ) в базе данных. Вы можете назначить любую сторону в качестве владельца, однако, если вы назначите одну сторону в качестве владельца, отношения не будут двунаправленными (обратная сторона aka "многие" не будет знать своего "владельца"). Это может быть желательно для инкапсуляции/свободный сцепление:
// "One" Customer owns the associated orders by storing them in a customer_orders join table public class Customer { @OneToMany(cascade = CascadeType.ALL) private List<Order> orders; } // if the Customer owns the orders using the customer_orders table, // Order has no knowledge of its Customer public class Order { // @ManyToOne annotation has no "mappedBy" attribute to link bidirectionally }
единственным решением для двунаправленного отображения является наличие у стороны "много" собственного указателя на "один" и использование атрибута @OneToMany "mappedBy". Без атрибута "mappedBy" Hibernate будет ожидать двойного сопоставления (база данных будет иметь как столбец join, так и таблицу join, что является избыточным (обычно нежелательным)).
// "One" Customer as the inverse side of the relationship public class Customer { @OneToMany(cascade = CascadeType.ALL, mappedBy = "customer") private List<Order> orders; } // "many" orders each own their pointer to a Customer public class Order { @ManyToOne private Customer customer; }
сущность, у которой есть таблица с внешним ключом в базе данных, является сущностью-владельцем, а другая таблица, на которую указывают, является обратной сущностью.
простые правила двунаправленных отношений:
1.Для двунаправленных отношений "многие к одному "сторона" многие " всегда является стороной владения. Пример: 1 комната имеет много человек (человек принадлежит только одна комната) - > владеющая сторона-это человек
2.Для однонаправленных двунаправленных отношений сторона-владелец соответствует стороне, содержащей соответствующий внешний ключ.
3.Для Много-ко-многим двунаправленных отношений, любая сторона может быть ведомой стороне.
Надежда может помочь вам.
для двух классов сущностей Customer и Order , hibernate создаст две таблицы.
Возможные Варианты:
mappedBy не используется в клиенте.Ява и порядок.класс java тогда ->
на стороне клиента будет создана новая таблица[name = CUSTOMER_ORDER], которая будет поддерживать сопоставление CUSTOMER_ID и ORDER_ID. Это первичные ключи таблиц клиентов и заказов. На стороне заказа требуется дополнительный столбец для сохранения соответствующего Customer_ID сопоставление записей.
mappedBy используется в клиенте.java [как указано в постановке задачи] Теперь дополнительная таблица [CUSTOMER_ORDER] не создается. Только один столбец в таблице
mappedby используется по порядку.Ява Теперь дополнительная таблица, которая будет создана в Hibernate.[name = CUSTOMER_ORDER] Таблица заказов не будет иметь дополнительного столбца [Customer_ID ] для сопоставления.
любая сторона может быть сделана владельцем отношений. Но его лучше выбрать xxxToOne сторону.
эффект кодирования - > только владеющая сторона сущности может изменить статус отношений. В приведенном ниже примере класс BoyFriend является владельцем отношений. даже если подруга хочет расстаться, она не может.
import javax.persistence.*; import java.util.ArrayList; import java.util.List; @Entity @Table(name = "BoyFriend21") public class BoyFriend21 { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Boy_ID") @SequenceGenerator(name = "Boy_ID", sequenceName = "Boy_ID_SEQUENCER", initialValue = 10,allocationSize = 1) private Integer id; @Column(name = "BOY_NAME") private String name; @OneToOne(cascade = { CascadeType.ALL }) private GirlFriend21 girlFriend; public BoyFriend21(String name) { this.name = name; } public BoyFriend21() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public BoyFriend21(String name, GirlFriend21 girlFriend) { this.name = name; this.girlFriend = girlFriend; } public GirlFriend21 getGirlFriend() { return girlFriend; } public void setGirlFriend(GirlFriend21 girlFriend) { this.girlFriend = girlFriend; } } import org.hibernate.annotations.*; import javax.persistence.*; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Table; import java.util.ArrayList; import java.util.List; @Entity @Table(name = "GirlFriend21") public class GirlFriend21 { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "Girl_ID") @SequenceGenerator(name = "Girl_ID", sequenceName = "Girl_ID_SEQUENCER", initialValue = 10,allocationSize = 1) private Integer id; @Column(name = "GIRL_NAME") private String name; @OneToOne(cascade = {CascadeType.ALL},mappedBy = "girlFriend") private BoyFriend21 boyFriends = new BoyFriend21(); public GirlFriend21() { } public GirlFriend21(String name) { this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public GirlFriend21(String name, BoyFriend21 boyFriends) { this.name = name; this.boyFriends = boyFriends; } public BoyFriend21 getBoyFriends() { return boyFriends; } public void setBoyFriends(BoyFriend21 boyFriends) { this.boyFriends = boyFriends; } } import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import java.util.Arrays; public class Main578_DS { public static void main(String[] args) { final Configuration configuration = new Configuration(); try { configuration.configure("hibernate.cfg.xml"); } catch (HibernateException e) { throw new RuntimeException(e); } final SessionFactory sessionFactory = configuration.buildSessionFactory(); final Session session = sessionFactory.openSession(); session.beginTransaction(); final BoyFriend21 clinton = new BoyFriend21("Bill Clinton"); final GirlFriend21 monica = new GirlFriend21("monica lewinsky"); clinton.setGirlFriend(monica); session.save(clinton); session.getTransaction().commit(); session.close(); } } import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import java.util.List; public class Main578_Modify { public static void main(String[] args) { final Configuration configuration = new Configuration(); try { configuration.configure("hibernate.cfg.xml"); } catch (HibernateException e) { throw new RuntimeException(e); } final SessionFactory sessionFactory = configuration.buildSessionFactory(); final Session session1 = sessionFactory.openSession(); session1.beginTransaction(); GirlFriend21 monica = (GirlFriend21)session1.load(GirlFriend21.class,10); // Monica lewinsky record has id 10. BoyFriend21 boyfriend = monica.getBoyFriends(); System.out.println(boyfriend.getName()); // It will print Clinton Name monica.setBoyFriends(null); // It will not impact relationship session1.getTransaction().commit(); session1.close(); final Session session2 = sessionFactory.openSession(); session2.beginTransaction(); BoyFriend21 clinton = (BoyFriend21)session2.load(BoyFriend21.class,10); // Bill clinton record GirlFriend21 girlfriend = clinton.getGirlFriend(); System.out.println(girlfriend.getName()); // It will print Monica name. //But if Clinton[Who owns the relationship as per "mappedby" rule can break this] clinton.setGirlFriend(null); // Now if Monica tries to check BoyFriend Details, she will find Clinton is no more her boyFriend session2.getTransaction().commit(); session2.close(); final Session session3 = sessionFactory.openSession(); session1.beginTransaction(); monica = (GirlFriend21)session3.load(GirlFriend21.class,10); // Monica lewinsky record has id 10. boyfriend = monica.getBoyFriends(); System.out.println(boyfriend.getName()); // Does not print Clinton Name session3.getTransaction().commit(); session3.close(); } }
Comments