Не пустое ограничение требует, чтобы вы вставили user.id в поле ссылки, но если вы установили поле id для автоматического создания, это значение не будет известно до окончания вставки.Чтобы решить эту проблему, вы можете использовать последовательность для генерации @ Id
create sequence SEQ_USER
и вставить первого пользователя, выбрав следующее значение этой последовательности и установив оба поля в это значение.С нативным SQL-запросом из JPA это выглядит так:
User u = new User();
u.setName("First User");
Query q = em.createNativeQuery("VALUES nextval for SEQ_USER");
Long nextId = Long.valueOf((Integer) q.getSingleResult());
q = em.createNativeQuery("insert into user (id, name, created_by) values (?, ?, ?)");
q.setParameter(1, nextId).setParameter(2, u.getName()).setParameter(3, nextId);
q.executeUpdate();
// don't forget to bring u into persistence context
u = em.find(User.class, nextId);
, что немного глупо, но вызывается только один раз.Все остальные пользователи будут сохранены обычным способом (используя SEQ_USER в качестве последовательности генератора для @Id)
В качестве альтернативы, вы можете написать свой собственный SequenceGenerator, сделав так:
public class UserIdGenerator implements IdentifierGenerator {
@Override
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
User o = (User) object;
Connection connection = session.connection();
try {
PreparedStatement ps = connection.prepareStatement("VALUES nextval for SEQ_USER");
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return rs.getLong(1);
}
} catch (SQLException e) {
log.error("Unable to generate Id: " + e.getMessage(), e);
}
return null;
}
}
In UserВы могли бы установить этот генератор как:
@Id
@GenericGenerator(name = "idSource", strategy = "com.example.db.UserIdGenerator", parameters = { @Parameter(name = "sequence", value = "SEQ_USER") })
@GeneratedValue(generator = "idSource")
private Long id;
, а затем
User u = new User();
u.setName("First User");
u.setCreatedBy(u);
em.persist(u);
работает как положено.