2016-02-19 2 views
1

У меня есть два объекта, двунаправленная активность (родительская) и разговор (ребенок). Я хочу сначала сохранить родительский элемент, и как только мой диалог или дочерний элемент будет создан. Я хочу обновить родительскую таблицу и вставить в дочерний элемент.Обновление родительской сущности перед вставкой дочернего объекта

Below is my Schema 

CREATE TABLE BIDIRECTIONAL_ACTIVITIES (
id bigint(20) NOT NULL AUTO_INCREMENT, 
status VARCHAR(255) NOT NULL, 
conversationId bigint(20), 
PRIMARY KEY(id) 
} 

create unique index index_conversationId on BIDIRECTIONAL_ACTIVITIES(conversationId); 

CREATE TABLE CONVERSATION (
id bigint(20) NOT NULL AUTO_INCREMENT, 
PRIMARY KEY(id), 
FOREIGN KEY(id) REFERENCES BIDIRECTIONAL_ACTIVITIES(conversationId) 
); 

Вот отображение в спящем OneToOne:

@Entity 
@Table(name="BIDIRECTIONAL_ACTIVITIES") 
public class BidirectionalActivity implements Serializable{ 
    @Id 
    @Column(name="id") 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Integer id; 

    @Column(name="status") 
    private String status; 

    @OneToOne(fetch = FetchType.LAZY, mappedBy="bidirectionalActivity", cascade=CascadeType.ALL) 
    @JoinColumn(name="conversationId") 
    private Conversation conversation; 
} 


@Entity 
@Table(name="CONVERSATION") 
public class Conversation implements Serializable{ 
    @Id 
    @Column(name="id") 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Integer id; 

@OneToOne(fetch = FetchType.LAZY) 
@PrimaryKeyJoinColumn 
    private BidirectionalActivity bidirectionalActivity; 
} 

DAO Layer

public class BidirectionalActivityDAOImpl implements BidirectionalActivityDAO { 
@Autowired 
private SessionFactory sessionFactory; 
@Override 
public void addBidirectionalActivity(BidirectionalActivity bidirectionalActivity) { 
     Session session = this.sessionFactory.getCurrentSession(); 
     session.saveOrUpdate(bidirectionalActivity); 
    } 
} 

Service Layer:

@Component 
public class BidirectionalActivityServiceImpl implements BidirectionalActivityService { 
    @Autowired 
    BidirectionalActivityDAO BidirectionalActivityDAO; 
    @Transactional 
    @Override 
    public Integer addBidirectionalActivity(BidirectionalActivity bidirectionalActivity) { 
     return BidirectionalActivityDAO.addBidirectionalActivity(bidirectionalActivity); 
    } 

Мой Контрольный пример:

BidirectionalActivity bidirectionalActivity = new BidirectionalActivity(); 
bidirectionalActivity.setStatus("Active"); 
Integer persistedIdBiderectionalActivity = bidirectionalActivityService.addBidirectionalActivity(bidirectionalActivity); 

Conversation conversation = new Conversation(); 
conversation.setBidirectionalActivity(persistedBidActvty); 
     persistedBidActvty.setConversation(conversation); 
    bidirectionalActivityService.addBidirectionalActivity(persistedBidActvty); 

Я ожидал, что спящий режим сначала выполнит инструкцию insert на родительской таблице, а во второй раз он должен сначала обновить родительскую таблицу, а затем дочернюю таблицу. , однако, его просто вставлять второй раз на детский стол.

insert into CONVERSATION values () 

и я получаю сообщение об ошибке:

Cannot add or update a child row: a foreign key constraint fails (`CONVERSATION`, CONSTRAINT `CONVERSATION_ibfk_1` FOREIGN KEY (`id`) REFERENCES `BIDIRECTIONAL_ACTIVITIES` (`conversationId`)) 
+0

Что-то не так с вашими рассуждениями. Как ваша «родительская таблица» двунаправлена ​​вообще, когда она имеет только ссылку на один разговор? Кроме того, почему бы вам не вставить беседу _first_ (и захватить ее идентификатор), а затем вставить родителя? – fge

ответ

1

Что происходит, когда новая строка переходит в CONVERSATION это время назначается auto_incrementing id системы.

Вашего внешнего ключ ограничение обеспечивает ссылочную целостность (RI), убедившись в том, что же id существует в строке в ссылке таблицы BIDIRECTIONAL_ACTIVITIES в колонке conversationId. Такая строка не существует.

Возможно, это не ваше желание установить RI как таковой.

Возможно, это то, что вы на самом деле имел в виду сделать:

CREATE TABLE CONVERSATION 
(
    id bigint(20) PRIMARY KEY, 
    FOREIGN KEY(id) REFERENCES BIDIRECTIONAL_ACTIVITIES(conversationId) 
); 

Просто канав AUTO_INCREMENT аспект от него и вручную положить в PK идентификатор, который определяется из родительской вставки в той определенной колонке conversationId в предшествующее шаг.

Независимо от того, вам нужно переосмыслить все это.

+0

Так что это лучший способ сделать это? – user2985842

+0

Для RI (и это хорошо, что вы этого хотите) убедитесь, что такая строка существует в * указанной таблице * BIDIRECTIONAL_ACTIVITIES' перед вставкой в ​​таблицу * ссылок * CONVERSATION'. Как это делается с помощью Hibernate выше моего уровня мастерства. Но, поскольку все это лежит на вершине RI-системы mysql, это то, о чем эта ошибка говорит вам. – Drew

+0

Вам действительно нужно отступить и подумать, почему вы настраиваете его так. Вы просто не знаете, что 'id' будет в дочерней таблице. Могут существовать недостатки двигателя или различные причины. Итак, опять-таки установка и ожидание кажутся совершенно неправильными. – Drew

Смежные вопросы