Почему нельзя присоединиться к 3-й таблице с помощью аннотации JPA TopLink?

У меня есть простые 3 таблицы:

Users
-id
-name

Addresses
-id
-user_id  //FK
-location

Phone
-id
-number
-address_id //FK
  • Пользователи могут иметь много адресов
  • Адресов может быть много.

Таким образом, аннотации, применяемые к каждому классу сущностей, будут выглядеть так:

Пользователи

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
    private List<Addresses> addresses;

Адреса

    @ManyToOne()
    @JoinColumn(name = "user_id")
    private Users user;

    @OneToMany(mappedBy = "address")
    private List<Phone> phone;

Телефон

    @ManyToOne()
    @JoinColumn(name = "address_id")
    private Addresses address;

Аннотация выше должна создавать отношения:

users  (1) ----- (n) addresses (1) ------ (n) phone

Затем я создал некоторые тестовые данные в MySQL и попытался запустить тест, чтобы увидеть, будет ли результат запроса, возвращающий «пользователей», включать ссылку на адреса и телефоны.

Я пробовал с 2 таблицами, используя только пользователей и адреса, и получил результат в порядке.

Теперь, когда я добавил таблицу «телефон», которая является третьей таблицей, я получаю сообщение об ошибке, показанное ниже. Это действительно правильный способ присоединиться к 3 или более таблицам?

Проверочный код

      try {
          //get entity manager
          String WEB_PU = "NoJSFPU";
          EntityManagerFactory factory =                 Persistence.createEntityManagerFactory(WEB_PU);
          EntityManager em = factory.createEntityManager();

          //run query
          List<Users> usersList = em.createQuery("SELECT u FROM Users u").getResultList();

           //loop to print out each result
           for(Users item : usersList) {
               //display user info
               System.out.println(item.getId() + " " + item.getFirstname());

               List<Addresses> addrs = item.getAddresses();
               for(Addresses ad : addrs) {
                  //display address info
                  System.out.println("Address:::" + ad.getLocation());

                  List<Phone> pho = ad.getPhone();
                  for(Phone p : pho) {
                     //display phone info
                     System.out.println("phone#" + p.getNumber());
                  }

                }//end inner for
            }//end outer for
                System.out.println("==========================");

            }
            catch(Exception e) {
                System.out.println("seriously wtf: " + e.toString());
                System.exit(1);
            }

Ошибка

Exception Description: predeploy for PersistenceUnit [NoJSFPU] failed.
Internal Exception: Exception [TOPLINK-7250] (Oracle TopLink Essentials - 2.0.1 (Build b09d-fcs (12/06/2007))): oracle.toplink.essentials.exceptions.ValidationException
Exception Description: [class local.test.session.Addresses] uses a non-entity [class local.test.session.Phone] as target entity in the relationship attribute [private java.util.List local.test.session.Addresses.phone].

person Meow    schedule 15.12.2010    source источник
comment
Тссс, я бы переименовал ваши таблицы Users и Addresses в User и Address. Не используйте множественное число в именах таблиц (ни в именах классов сущностей).   -  person BalusC    schedule 15.12.2010
comment
Привет BalusC, давно пора видеть! Спасибо за совет, но в чем причина использования единственного числа для имен таблиц? Это стандартизированное соглашение?   -  person Meow    schedule 16.12.2010


Ответы (1)


Я понял. Пришлось указать с помощью аннотации @JoinTable.

Теперь, если я запускаю тестовый код, можно получить данные из всех трех таблиц: D

Адреса

@ManyToOne
@JoinTable(name = "Addresses", joinColumns = {@JoinColumn(name="user_id", 
referencedColumnName = "user_id") } )
private Users user;

Телефон

@ManyToOne
@JoinTable(name = "Phone", joinColumns = {@JoinColumn(name="address_id", 
referencedColumnName = "address_id") } )
private Addresses address;
person Meow    schedule 15.12.2010