JPA не сохраняет внешний ключ в отношении @OneToMany

StackOverflow https://stackoverflow.com/questions/814474

  •  03-07-2019
  •  | 
  •  

Вопрос

Я использую 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;
    }
}

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

Это было полезно?

Решение

Вы должны сами управлять отношениями 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;

  ...
}

Другие советы

В ответ на ответ Клетуса. Я бы сказал, что важно иметь аннотацию @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);
    }
}

Если отношение Контакт-телефон является однонаправленным, вы также можете заменить 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 - > Родитель - ссылка на ребенка (внешний ключ)

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

phone.setContact(contact);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top