Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
JPAContainer: ManytoOne relation with EmbeddedID
There are questions similar but not quite. In those cases (and in the JPAContainer examples) the Entity part of the ManyToOne relationship has a single key. In my case it is an embedded id.
My code is based on the Address Book example.
Here are the two entities:
@Entity
@Table(name = "tutorial")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Tutorial.findAll", query = "SELECT t FROM Tutorial t"),
@NamedQuery(name = "Tutorial.findById", query = "SELECT t FROM Tutorial t WHERE t.tutorialPK.id = :id"),
@NamedQuery(name = "Tutorial.findByTutorialTypeId", query = "SELECT t FROM Tutorial t WHERE t.tutorialPK.tutorialTypeId = :tutorialTypeId"),
@NamedQuery(name = "Tutorial.findByMessage", query = "SELECT t FROM Tutorial t WHERE t.message = :message")})
public class Tutorial implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected TutorialPK tutorialPK;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 245)
@Column(name = "message")
private String message;
@JoinColumn(name = "tutorial_type_id", referencedColumnName = "id", insertable = false, updatable = false)
@ManyToOne(optional = false)
private TutorialType tutorialType;
public Tutorial() {
}
public Tutorial(TutorialPK tutorialPK) {
this.tutorialPK = tutorialPK;
}
public Tutorial(TutorialPK tutorialPK, String message) {
this.tutorialPK = tutorialPK;
this.message = message;
}
public Tutorial(int id, int tutorialTypeId) {
this.tutorialPK = new TutorialPK(id, tutorialTypeId);
}
public TutorialPK getTutorialPK() {
return tutorialPK;
}
public void setTutorialPK(TutorialPK tutorialPK) {
this.tutorialPK = tutorialPK;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public TutorialType getTutorialType() {
return tutorialType;
}
public void setTutorialType(TutorialType tutorialType) {
this.tutorialType = tutorialType;
}
@Override
public int hashCode() {
int hash = 0;
hash += (tutorialPK != null ? tutorialPK.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Tutorial)) {
return false;
}
Tutorial other = (Tutorial) object;
if ((this.tutorialPK == null && other.tutorialPK != null) || (this.tutorialPK != null && !this.tutorialPK.equals(other.tutorialPK))) {
return false;
}
return true;
}
@Override
public String toString() {
return "games.jwrestling.server.game.db.persistence.Tutorial[ tutorialPK=" + tutorialPK + " ]";
}
}
And the EmbeddedId class:
@Embeddable
public class TutorialPK implements Serializable {
@Basic(optional = false)
@NotNull
@Column(name = "id")
private int id;
@Basic(optional = false)
@NotNull
@Column(name = "tutorial_type_id")
private int tutorialTypeId;
public TutorialPK() {
}
public TutorialPK(int id, int tutorialTypeId) {
this.id = id;
this.tutorialTypeId = tutorialTypeId;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getTutorialTypeId() {
return tutorialTypeId;
}
public void setTutorialTypeId(int tutorialTypeId) {
this.tutorialTypeId = tutorialTypeId;
}
@Override
public int hashCode() {
int hash = 0;
hash += (int) id;
hash += (int) tutorialTypeId;
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof TutorialPK)) {
return false;
}
TutorialPK other = (TutorialPK) object;
if (this.id != other.id) {
return false;
}
if (this.tutorialTypeId != other.tutorialTypeId) {
return false;
}
return true;
}
@Override
public String toString() {
return "games.jwrestling.server.game.db.persistence.TutorialPK[ id=" + id + ", tutorialTypeId=" + tutorialTypeId + " ]";
}
}
I got the form set up and it works fine when I edit the items, but creating I get errors because the TutorialPK is null:
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.2.v20151217-774c696): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'tutorial_type_id' cannot be null
Here are the related Vaadin code:
public final class TutorialEditor extends Window implements Button.ClickListener,
FormFieldFactory {
private final Item tutorialItem;
private final Form editorForm;
private final Button saveButton;
private final Button cancelButton;
public TutorialEditor(Item tutorialItem) {
this.tutorialItem = tutorialItem;
editorForm = new Form();
editorForm.setFormFieldFactory(this);
editorForm.setBuffered(true);
editorForm.setImmediate(true);
editorForm.setItemDataSource(tutorialItem, Arrays.asList("message",
"tutorialType"));
saveButton = new Button("Save", this);
cancelButton = new Button("Cancel", this);
editorForm.getFooter().addComponent(saveButton);
editorForm.getFooter().addComponent(cancelButton);
setSizeUndefined();
setContent(editorForm);
setCaption("New Tutorial");
}
@Override
public void buttonClick(Button.ClickEvent event) {
if (event.getButton() == saveButton) {
editorForm.commit();
fireEvent(new EditorSavedEvent(this, tutorialItem));
} else if (event.getButton() == cancelButton) {
editorForm.discard();
}
close();
}
@Override
public Field<?> createField(Item item, Object propertyId, Component uiContext) {
Field field = DefaultFieldFactory.get().createField(item, propertyId,
uiContext);
if ("tutorialType".equals(propertyId)) {
field = new TutorialTypeSelector();
} else if (field instanceof TextField) {
((TextField) field).setNullRepresentation("");
}
field.addValidator(new BeanValidator(Tutorial.class, propertyId
.toString()));
return field;
}
public void addListener(EditorSavedListener listener) {
try {
Method method = EditorSavedListener.class.getDeclaredMethod(
"editorSaved", new Class{EditorSavedEvent.class});
addListener(EditorSavedEvent.class, listener, method);
} catch (final java.lang.NoSuchMethodException e) {
// This should never happen
throw new java.lang.RuntimeException(
"Internal error, editor saved method not found");
}
}
public void removeListener(EditorSavedListener listener) {
removeListener(EditorSavedEvent.class, listener);
}
public static class EditorSavedEvent extends Component.Event {
private final Item savedItem;
public EditorSavedEvent(Component source, Item savedItem) {
super(source);
this.savedItem = savedItem;
}
public Item getSavedItem() {
return savedItem;
}
}
public interface EditorSavedListener extends Serializable {
public void editorSaved(EditorSavedEvent event);
}
And another one:
class TutorialTypeSelector extends CustomField<TutorialType> {
private final JPAContainer<TutorialType> container;
private final ComboBox type = new ComboBox();
public TutorialTypeSelector() {
container = JPAContainerFactory.make(TutorialType.class,
"JWPUJNDI");
setCaption("Type");
type.setContainerDataSource(container);
type.setItemCaptionPropertyId("type");
type.addListener(new Property.ValueChangeListener() {
@Override
public void valueChange(
com.vaadin.data.Property.ValueChangeEvent event) {
/*
* Modify the actual value of the custom field.
*/
if (type.getValue() == null) {
setValue(null, false);
} else {
TutorialType entity = container
.getItem(type.getValue()).getEntity();
setValue(entity, false);
}
}
});
}
@Override
protected Component initContent() {
CssLayout cssLayout = new CssLayout();
cssLayout.addComponent(type);
return cssLayout;
}
@Override
public void setPropertyDataSource(Property newDataSource) {
super.setPropertyDataSource(newDataSource);
setTutorialType((TutorialType) newDataSource.getValue());
}
@Override
public void setValue(TutorialType newValue) throws ReadOnlyException,
Converter.ConversionException {
super.setValue(newValue);
setTutorialType(newValue);
}
private void setTutorialType(TutorialType type) {
this.type.setValue(type != null ? type.getId() : null);
}
@Override
public Class<? extends TutorialType> getType() {
return TutorialType.class;
}
}
Any idea on how to populate this field? See related Stackoverflow question here.