package io.ebeaninternal.server.persist.dml;
import io.ebean.bean.EntityBean;
import io.ebean.util.JdbcClose;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.core.Message;
import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.persist.DmlUtil;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class InsertHandler extends DmlHandler {
private final InsertMeta meta;
private final boolean concatinatedKey;
private boolean useGeneratedKeys;
private boolean useSelectLastInsertedId;
public InsertHandler(PersistRequestBean<?> persist, InsertMeta meta) {
super(persist, meta.isEmptyStringToNull());
this.meta = meta;
this.concatinatedKey = meta.isConcatenatedKey();
}
@Override
public boolean isUpdate() {
return false;
}
@Override
public void bind() throws SQLException {
BeanDescriptor<?> desc = persistRequest.getBeanDescriptor();
EntityBean bean = persistRequest.getEntityBean();
Object idValue = desc.getId(bean);
boolean withId = !DmlUtil.isNullOrZero(idValue);
if (!withId) {
if (concatinatedKey) {
withId = meta.deriveConcatenatedId(persistRequest);
} else if (meta.supportsGetGeneratedKeys()) {
useGeneratedKeys = true;
} else {
useSelectLastInsertedId = meta.supportsSelectLastInsertedId();
}
}
SpiTransaction t = persistRequest.getTransaction();
sql = meta.getSql(withId, persistRequest.isPublish());
PreparedStatement pstmt;
if (persistRequest.isBatched()) {
pstmt = getPstmt(t, sql, persistRequest, useGeneratedKeys);
} else {
pstmt = getPstmt(t, sql, useGeneratedKeys);
}
dataBind = bind(pstmt);
meta.bind(this, bean, withId, persistRequest.isPublish());
if (persistRequest.isBatched()) {
batchedPstmt.registerInputStreams(dataBind.getInputStreams());
}
logSql(sql);
}
@Override
protected PreparedStatement getPstmt(SpiTransaction t, String sql, boolean useGeneratedKeys) throws SQLException {
Connection conn = t.getInternalConnection();
if (useGeneratedKeys) {
return conn.prepareStatement(sql, meta.getIdentityDbColumns());
} else {
return conn.prepareStatement(sql);
}
}
@Override
public int execute() throws SQLException, OptimisticLockException {
int rowCount = dataBind.executeUpdate();
if (useGeneratedKeys) {
getGeneratedKeys();
} else if (useSelectLastInsertedId) {
fetchGeneratedKeyUsingSelect();
}
checkRowCount(rowCount);
return rowCount;
}
private void getGeneratedKeys() throws SQLException {
ResultSet rset = dataBind.getPstmt().getGeneratedKeys();
try {
setGeneratedKey(rset);
} finally {
JdbcClose.close(rset);
}
}
private void setGeneratedKey(ResultSet rset) throws SQLException {
if (rset.next()) {
Object idValue = rset.getObject(1);
if (idValue != null) {
persistRequest.setGeneratedKey(idValue);
}
} else {
throw new PersistenceException(Message.msg("persist.autoinc.norows"));
}
}
private void fetchGeneratedKeyUsingSelect() throws SQLException {
PreparedStatement stmt = null;
ResultSet rset = null;
try {
stmt = transaction.getConnection().prepareStatement(persistRequest.getSelectLastInsertedId());
rset = stmt.executeQuery();
setGeneratedKey(rset);
} finally {
JdbcClose.close(rset);
JdbcClose.close(stmt);
}
}
}