ECard:
@Entity
@Table (name = "ecard")
public class Ecard {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@OneToOne (cascade = CascadeType.ALL)
@JoinColumn(name = "IdUser", nullable = false)
private User user;
@ManyToOne
@JoinColumn(name = "IdBank", nullable = false)
private Bank bank;
@Column (name = "accountNumber", nullable = false)
private int accountNumber;
public ECard(User user, Bank bank, int accNumber) {
this.user = user;
this.bank = bank;
this.accountNumber = accNumber;
}
}
User:
@Entity
@Table (name="user")
public class User {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@OneToOne (mappedBy = "user")
private ECard eCard;
@ManyToOne
@JoinTable(
name = "ecard",
inverseJoinColumns = @JoinColumn(name = "IdBank", referencedColumnName = "Id"),
joinColumns = @JoinColumn(name = "IdUser", referencedColumnName = "Id")
)
private Bank bank;
public void seteCard(ECard eCard) {
this.eCard = eCard;
}
public void setBank(Bank bank) {
this.bank = bank;
}
}
Bank:
@Entity
@Table (name = "bank")
public class Bank {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column(name = "name", nullable = false, unique = true)
private String name;
}
I have already initialized Bank table and I would like to insert new User with new ECard linked to Bank that already exists in database
I'm new to this whole thing so I can't understand why
My code that won't work:
//I checked and variable bank is okay, it's method argument
eManager.getTransaction().begin();
User user = new User();
ECard eCard = new ECard(user, bank, 1000);
user.seteCard(eCard);
user.setBank(bank); // PROBLEM
eManager.persist(eCard);
eManager.getTransaction().commit();
I get a rollback Exception:
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Field 'accountNumber' doesn't have a default value
Error Code: 1364
Call: INSERT INTO ecard (IdBank, IdUser) VALUES (?, ?)
bind => [2 parameters bound]
Query: DataModifyQuery(name="bank" sql="INSERT INTO ecard (IdBank, IdUser) VALUES (?, ?)")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:895)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:957)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:630)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1995)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:296)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:271)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:251)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.executeNoSelect(StatementQueryMechanism.java:118)
at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2894)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1797)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1779)
at org.eclipse.persistence.mappings.OneToOneMapping.performDataModificationEvent(OneToOneMapping.java:2181)
at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:159)
at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:4200)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1439)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1529)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:277)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1167)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:132)
... 10 more
Caused by: java.sql.SQLException: Field 'accountNumber' doesn't have a default value
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2794)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:885)
... 34 more
Java Result: 1
When i delete line user.setBank(bank)
it works great, but I need reference on Bank in User, so deleting this line isn't so good for me.
When I put default value for accountNumber, I get two rows in eCard table, one regular row and second row with default accountNumber and same IdUser and IdBank
How to avoid that exception and how to set reference on Bank??
You are already declaring ecard
as your mapping table by adding this
@ManyToOne
@JoinTable(
name = "ecard",
inverseJoinColumns = @JoinColumn(name = "IdBank", referencedColumnName = "Id"),
joinColumns = @JoinColumn(name = "IdUser", referencedColumnName = "Id")
)
But ecard
is also used as an entity to map information of user and bank by associating bankId and userId plus an accountNumber field.
That's why Jpa is adding 2 record in persist of user - one for defined mapping in user class name = 'ecard'
mapping and one for the ECard eCard = new ECard(user, bank, 1000);
I would suggest you move accountNumber field to bank class and delete ecard
class because mapping in JoinColumn (name = 'ecard'...
already assumes there exists a table ecard
with just 2 columns userId and bankId and would handle it in default way.
Or remove the bank field in user class because user already has reference to ecard
which has reference to bank
.But now you will have to manage the association between bank and user manually like you are doing it in above code.