2017-01-27 19 views
0

Ecard:Как предотвратить исключение откат JPA после вставки?

@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; 
    } 
} 

Пользователь:

 @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; 
} 

Я уже инициализирован банка таблицу, и я хотел бы, чтобы вставить новый пользователь с новым Ecard связан с банком, который уже существует в базе данных

Я новичок в это все дело, так что я не могу понять, почему

Моего код, который не будет работать:

 //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(); 

я получаю исключение отката:

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 

Когда я удалить строку user.setBank(bank) он прекрасно работает , но мне нужна ссылка на Bank in User, поэтому удаление этой строки не так хорошо для меня.

Когда я ставлю значение по умолчанию для ACCOUNTNUMBER, я получаю две строки в электронную открытку таблице, один регулярный ряд и второй ряд с по умолчанию ACCOUNTNUMBER и тот же IdUser и IdBank

Как избежать этого исключения и как установить ссылку на банк ??

+0

Можете ли вы показать нам схему базы данных, это может быть проблемой с определением Банка в вашей базе данных. У меня были такие проблемы, и в большинстве случаев первичный ключ не определен правильно в проблемном объекте. Или отсутствует флаг автоматического увеличения. Или, точнее, описание банковского стола. – Nord

+0

accountNumber не имеет значения. Строка, о которой вы упоминаете, похоже, влияет на это поле – efekctive

+0

Также проверьте, что accountNumber является допустимым номером учетной записи. Поскольку accountNumber является int, он должен присутствовать и не может быть установлен в Null. – Nord

ответ

0

Вы уже объявляя ecard как ваше отображение таблицы, добавив этот

@ManyToOne 
    @JoinTable(
     name = "ecard", 
     inverseJoinColumns = @JoinColumn(name = "IdBank", referencedColumnName = "Id"), 
     joinColumns = @JoinColumn(name = "IdUser", referencedColumnName = "Id") 
    ) 

Но ecard также используется в качестве объекта для сопоставления информации пользователя и банка, связывая bankId и USERID плюс поле ACCOUNTNUMBER. Вот почему JPA добавляет 2 записи в упорствовать пользователя - один для определенного отображения в классе пользователя name = 'ecard' отображения и один для ECard eCard = new ECard(user, bank, 1000);

Я хотел бы предложить вам двигаться ACCOUNTNUMBER поле для банковского класса и удалять ecard класс, потому что отображение в JoinColumn (name = 'ecard'... уже предполагает, что существует таблица ecard с двумя столбцами userId и bankId и будет обрабатывать ее по умолчанию.

Или удалите поле банка в пользовательском классе, потому что пользователь уже ссылается на ecard, который имеет ссылку на bank. Но теперь вам нужно будет управлять связью между банком и пользователем вручную, как будто вы делаете это в приведенном выше коде.

+0

Большое спасибо, теперь это понятно! Отличный ответ –

+0

Единственный недостаток, который я вижу при удалении класса карты, заключается в том, что у вас есть таблица без отображения. Если вы наберете его позже, вам нужно убедиться, что вы не попадете в это снова – efekctive

 Смежные вопросы

  • Нет связанных вопросов^_^