JPA не сохраняет внешний ключ в отношении @OneToMany - PullRequest
18 голосов
/ 02 мая 2009

Я использую Spring с Hibernate в качестве поставщика JPA и пытаюсь получить @OneToMany (контакт, имеющий много телефонных номеров), чтобы сохранить внешний ключ в таблице телефонных номеров. Из моей формы я получаю контактный объект, в котором есть список номеров телефонов. Контакт сохраняется правильно (Hibernate выбирает PK из указанной последовательности). Список телефонов (номеров) также сохраняется с правильным PK, но нет FK в таблице контактов.

public class Contact implements Serializable {

    @OneToMany(mappedBy = "contactId", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
    private List<Phone> phoneList;

}

public class Phone implements Serializable {

    @JoinColumn(name = "contact_id", referencedColumnName = "contact_id")
    @ManyToOne
    private Contact contactId;

}

@Repository("contactDao")
@Transactional(readOnly = true)
public class ContactDaoImpl implements ContactDao {

    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void save(Contact c) {
        em.persist(c);
        em.flush();
    }
}


@Controller
public class ContactController {
    @RequestMapping(value = "/contact/new", method = RequestMethod.POST)
    public ModelAndView newContact(Contact c) {
        ModelAndView mv = new ModelAndView("contactForm");
        contactDao.save(c);
        mv.addObject("contact", c);
        return mv;
    }
}

Надеюсь, я получил все соответствующие биты выше, в противном случае, пожалуйста, дайте мне знать.

Ответы [ 4 ]

23 голосов
/ 02 мая 2009

Вы должны сами управлять отношениями с Java. Для такого рода вещей вам нужно что-то вроде:

@Entity
public class Contact {
  @Id
  private Long id;

  @OneToMany(cascade = CascadeType.PERSIST, mappedBy = "contact")
  private List<Phone> phoneNumbers;

  public void addPhone(PhoneNumber phone) {
     if (phone != null) {
        if (phoneNumbers == null) {
            phoneNumbers = new ArrayList<Phone>();          
        }
        phoneNumbers.add(phone);
        phone.setContact(this);
     }
  }

  ...
}

@Entity
public class Phone {
  @Id
  private Long id;

  @ManyToOne
  private Contact contact;

  ...
}
6 голосов
/ 04 мая 2009

В ответ на ответ Клетуса. Я бы сказал, что важно иметь аннотацию @column в полях id, а также все элементы последовательности. Альтернативой использованию параметра mappedBy аннотации @OneToMany является использование аннотации @JoinColumn.

В качестве своего рода стороннего подхода необходимо рассмотреть реализацию вашего addPhone. Вероятно, это должно быть что-то вроде.

public void addPhone(PhoneNumber phone) {
    if (phone == null) {
        return;
    } else {
        if (phoneNumbers == null) {
            phoneNumbers = new ArrayList<Phone>();
        }
        phoneNumbers.add(phone);
        phone.setContact(this);
    }
}
2 голосов
/ 01 декабря 2017

Если контакт-телефон является однонаправленным, вы также можете заменить mappedBy в @OneToMany аннотации на @JoinColumn(name = "contact_id").

@Entity
public class Contact {
  @Id
  private Long id;

  @OneToMany(cascade = CascadeType.PERSIST)
  @JoinColumn(name = "contact_id")
  private List<Phone> phoneNumbers;

  // normal getter/setter
  ...
}

@Entity
public class PhoneNumber {
  @Id
  private Long id;

  ...
}

Аналогично в JPA @OneToMany -> Родитель - дочерний элемент (внешний ключ)

2 голосов
/ 10 сентября 2015

Я не думаю, что метод addPhone необходим, нужно только установить контакт в объекте телефона:

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