Cascade保存子实体失败了JPA(Spring数据+ Hibernate)?

时间:2018-03-30 15:49:43

标签: hibernate jpa spring-data-jpa

我有一个非常简单的用例,我有2个实体:客户端和电子邮件(客户端有OneToMany电子邮件)。

当我尝试单独保存电子邮件时,它没有错误,我可以在数据库中看到它:

void WebSocketManager::Handshake()
{
    qDebug() << "WebSocketManager::Handshake";

    try {
        HTTPResponse response;
        QString origin = Settings::Instance()->GetErPortal();
        QString host = origin.remove("http://");
        host = host.remove('/');
        QString token = "/event/bus/ws/subscribe?auth_token=" + Settings::Instance()->token().toUtf8();

        _wssession.setHost(host.toUtf8().constData());
        _wssession.setPort(80);

        HTTPRequest request(HTTPRequest::HTTP_GET, token.toUtf8().constData(),HTTPMessage::HTTP_1_1);
        request.set("origin", origin.toUtf8().constData());

        _wssock = new WebSocket(_wssession, request, response);
        response.getStatus();

        HTTPResponse::HTTPStatus status = response.getStatus();
        qDebug() << "Handshake status is : " << status;

        if(status == HTTPResponse::HTTPStatus::HTTP_SWITCHING_PROTOCOLS)
            _status = true;
    }
    catch (std::exception &e)
    {
        qDebug() << "WebSocketManager::Handshake exception " << e.what();
    }
}

void WebSocketManager::Read()
{
    char receiveBuff[1024];

    while(_status)
    {

        qDebug() << "WebSocketManager::Read wait data...., thread = " << QThread::currentThread();

        try {
            int flags=0;
            int rlen=_wssock->receiveFrame(receiveBuff,1024,flags);

            if(!rlen)
            {
                qDebug() << "WebSocketManager::Read error";
                emit ConnectionFailed();
                return;
            }
            else
            {
                qDebug() << "WebSocketManager::Read, len =" << rlen << ", flags = " << flags << ", data = " << receiveBuff;
                ProcessBackendEvent(QString(receiveBuff));
            }
        }
        catch (std::exception &e)
        {
            qDebug() << "WebSocketManager::Read exception " << e.what();
        }

    }
}

但是当我尝试使用cascade保存新客户端及其电子邮件的主要用例时,我收到错误:

测试用例:

  @Test
  public void insertEmail() {

    Client fetchedClient = clientRepository.findClientsFullByPdlClient("25492040401007");

    Email email = new Email();
    email.setClient(fetchedClient);
    email.setEmail("toto@gmail.com");

    emailRepository.save(email);
  }

错误:

  @Test
  public void testCreateClient() {

    Client client = new Client();
    client.setPdlClient(PDL_CLIENT_TO_CREATE);    

    Email email1 = new Email();
    email1.setEmail("toto@gmail.com");
    email1.setOrdre((short) 1);
    client.addEmail(email1);

    Email email2 = new Email();
    email2.setEmail("toto@sfr.com");
    email2.setOrdre((short) 2);
    client.addEmail(email2);

    clientRepository.save(client);

  }

来自客户的相关部分(由Dali + EclipseLink工具生成):

WARN  o.h.e.jdbc.spi.SqlExceptionHelper - SQL Error: 1048, SQLState: 23000
ERROR o.h.e.jdbc.spi.SqlExceptionHelper - Column 'EMAIL' cannot be null

Email.java(没有getter / setters):

//bi-directional many-to-one association to Email
@OneToMany(cascade = CascadeType.ALL, mappedBy="client")
private List<Email> emails = new ArrayList<Email>();

public Email addEmail(Email email) {
    getEmails().add(email);
    email.setClient(this);

    return email;
}

现在如果我在上面显示的成功的单个电子邮件插入后立即尝试我的级联保存,我会收到一个不同的错误,显示我的“email”属性已设置且可读!

@Entity
@Table(name="EMAIL")
public class Email {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="ID_EMAIL")
    private Integer idEmail;

    @Column(name="EMAIL")
    private String email;

    //bi-directional many-to-one association to Client
    @ManyToOne
    @JoinColumn(name="ID_CLIENT")
    private Client client;
}

所以我有点困惑。我究竟做错了什么 ?如果它抱怨缺少ID_CLIENT,我会理解,但这个“'EMAIL'不能为空”,它是什么意思?

1 个答案:

答案 0 :(得分:1)

好的,我的不好,上面的所有代码实际上都在工作。

我有一个错字:

Email email2 = new Email();
email.setEmail("toto@sfr.com");
email.setOrdre((short) 2);
client.addEmail(email2);

而不是:

Email email2 = new Email();
email2.setEmail("toto@sfr.com");
email2.setOrdre((short) 2);
client.addEmail(email2);

我可以删除这个问题,但也许这对其他人来说可能是一个有用的工作示例。