2016-03-05 52 views
2

我已經嘗試了一些在網絡上找到的解決方案,他們都沒有工作。我正在使用內存中的持久化hibernate數據庫。org.h2.jdbc.JdbcSQLException:NULL不允許列「ID」

@Entity 
@Table(name = "Users") 
public class User implements Serializable { 

    private String id; 

    private String username; 

    private String password; 

    private String email; 



    private Boolean enabled; 


    private Event checkedInEvent; 

    @Id 
    @GeneratedValue(generator="uuid", strategy = GenerationType.AUTO) 
    @GenericGenerator(name = "uuid", strategy = "uuid2") 
    @Column(name = "id", unique = true) 
    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    @Column(name = "username") 
    public String getUsername() { 
     return username; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    @Column(name = "password") 
    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    @PrePersist 
    public void encryptPassword() throws Exception { 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     md.update(password.getBytes()); 
     byte byteData[] = md.digest(); 
     //convert the byte to hex format method 1 
     StringBuffer sb = new StringBuffer(); 
     for (int i = 0; i < byteData.length; i++) { 
      sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)); 
     } 
     password = sb.toString(); 
    } 

    @Column(name = "email") 
    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 


    @Column(name = "enabled") 
    public Boolean getEnabled() { 
     return enabled; 
    } 

    public void setEnabled(Boolean enabled) { 
     this.enabled = enabled; 
    } 

    @PostLoad 
    public void postLoad() 
    { 
     password = null; 
    } 


    @ManyToOne(optional=true,cascade=CascadeType.ALL) 
    @JoinTable 
    (
     name="CheckedInUsers", 
     joinColumns={ @JoinColumn(name="checkedInUsersId", referencedColumnName="id") }, 
     inverseJoinColumns={ @JoinColumn(name="checkedInEventsId", referencedColumnName="id") } 
    ) 
    public Event getCheckedInEvent() { 
     return checkedInEvent; 
    } 

    public void setCheckedInEvent(Event checkedInEvent) { 
     this.checkedInEvent = checkedInEvent; 
    } 
} 

經過在用戶

@Entity 
@Table(name = "CheckedInUsers") 
public class CheckedInUsers { 

    private String id; 

    private String checkedInEventsId; 

    private String checkedInUsersId; 

    @Id 
    @GeneratedValue(generator="uuid") 
    @GenericGenerator(name = "uuid", strategy = "uuid2") 
    @Column(name = "id", unique = true) 
    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    @Column(name = "checkedInEventsId") 
    public String getEvent() { 
     return checkedInEventsId; 
    } 

    public void setEvent(String event) { 
     this.checkedInEventsId = event; 
    } 

    @Column(name = "checkedInUsersId") 
    public String getUser() { 
     return checkedInUsersId; 
    } 

    public void setUser(String user) { 
     this.checkedInUsersId = user; 
    } 
} 

事件
@Entity 
@Spatial(spatialMode = SpatialMode.GRID) 
@Indexed 
@Table(name = "Events") 
public class Event { 

    private String id; 

    private String name; 

    private Date startTime; 

    private Venue venue; 

    private Set<User> checkedInUsers; 


    @Id 
    @DocumentId 
    @GeneratedValue(generator="uuid") 
    @GenericGenerator(name = "uuid", strategy = "uuid2") 
    @Column(name = "id", unique = true) 
    @Field(name = "id") 
    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    @Column(name = "name") 
    @Field(name = "name") 
    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Column(name = "starttime") 
    @Temporal(TemporalType.TIMESTAMP) 
    @Field(name = "starttime") 
    public Date getStartTime() { 
     return startTime; 
    } 

    public void setStartTime(Date startTime) { 
     this.startTime = startTime; 
    } 


    @ManyToOne(optional=false,targetEntity = Venue.class) 
    @JoinColumn(name="venueid",referencedColumnName="id") 
    @JsonBackReference 
    public Venue getVenue() { 
     return venue; 
    } 

    @OneToMany(mappedBy = "checkedInEvent") 
    @Fetch(FetchMode.JOIN) 
    public Set<User> getCheckedInUsers() { 
     return checkedInUsers; 
    } 

    public void setCheckedInUsers(Set<User> checkedInUsers) { 
     this.checkedInUsers = checkedInUsers; 
    } 

    public void setVenue(Venue venue) { 
     this.venue = venue; 
    } 

} 

誤差
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:259) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225) 
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:131) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) 
    at com.sun.proxy.$Proxy110.save(Unknown Source) 
    at Superior.TestCases.Config.TestDataSetup.setUpEastonEvents(TestDataSetup.java:130) 
    at Superior.TestCases.Config.TestDataSetup.setUpVenues(TestDataSetup.java:81) 
    at Superior.TestCases.Config.TestDataSetup.setUp(TestDataSetup.java:65) 
    at Superior.TestCases.Tests.Models.TestAppManager.setup(TestAppManager.java:73) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) 
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement 
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211) 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3127) 
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3190) 
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525) 
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56) 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1258) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177) 
    at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77) 
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) 
    ... 46 common frames omitted 
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "ID"; SQL statement: 
insert into CheckedInUsers (checkedInEventsId, checkedInUsersId) values (?, ?) [23502-191] 
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) 
    at org.h2.message.DbException.get(DbException.java:179) 
    at org.h2.message.DbException.get(DbException.java:155) 
    at org.h2.table.Column.validateConvertUpdateSequence(Column.java:307) 
    at org.h2.table.Table.validateConvertUpdateSequence(Table.java:779) 
    at org.h2.command.dml.Insert.insertRows(Insert.java:151) 
    at org.h2.command.dml.Insert.update(Insert.java:114) 
    at org.h2.command.CommandContainer.update(CommandContainer.java:98) 
    at org.h2.command.Command.executeUpdate(Command.java:258) 
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:160) 
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:146) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) 
    ... 60 common frames omitted 

將被持久保存的數據

user = new User(); 
    user.setUsername("billTheTester"); 
    user.setEmail("[email protected]"); 
    user.setPassword("test123"); 
    user = daoManager.getUserRepo().save(user); 
    this.testUserTwo = user; 

    Calendar cal = Calendar.getInstance(); 
    Event event = new Event(); 
    event.setName("Hanging Out!"); 
    event.setVenue(venue); 
    event.setStartTime(cal.getTime()); 
    event = daoManager.getEventRepo().save(event); 
    testUserTwo.setCheckedInEvent(event); 
    daoManager.getUserRepo().save(testUserTwo); 

數據源配置

package Superior.Config.DatabaseConfig;

import org.hibernate.SessionFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Primary; 
import org.springframework.context.annotation.PropertySource; 
import org.springframework.core.annotation.Order; 
import org.springframework.core.env.Environment; 
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 
import org.springframework.jdbc.datasource.DriverManagerDataSource; 
import org.springframework.orm.jpa.JpaTransactionManager; 
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; 
import org.springframework.transaction.PlatformTransactionManager; 
import org.springframework.transaction.annotation.EnableTransactionManagement; 

import javax.persistence.EntityManagerFactory; 
import javax.sql.DataSource; 
import java.util.HashMap; 
import java.util.Properties; 


@Configuration 
@PropertySource({ "classpath:application.properties" }) 
@EnableTransactionManagement 
@EnableJpaRepositories(basePackages = "Superior.Models", 
     entityManagerFactoryRef = "prodEntityManager", 
     transactionManagerRef = "transactionManager" 
) 
@Order(1) 
public class PrimaryDatasourceConfig { 

    @Autowired 
    private Environment env; 

    HashMap<String, Object> properties = new HashMap<String, Object>(); 

    @Bean(name = "prodDataSource") 
    public DataSource prodDataSource() { 
     Properties props = new Properties(); 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
     dataSource.setUrl(env.getProperty("hibernate.connection.url")); 
//  dataSource.setUsername(env.getProperty("hibernate.username")); 

     return dataSource; 
    } 

    @Primary 
    @Bean(name = "prodEntityManager") 
    public SuperiorLocalContainerEntityManagerFactoryBean prodEntityManager() { 
     SuperiorLocalContainerEntityManagerFactoryBean em = new SuperiorLocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(prodDataSource()); 
     em.setPackagesToScan(new String[]{"Superior.Models.Tables"}); 

     HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     em.setJpaVendorAdapter(vendorAdapter); 
     this.properties = new HashMap<String, Object>(); 
     properties.put("hibernate.dialect", 
       env.getProperty("hibernate.dialect")); 
     properties.put("hibernate.hbm2ddl.auto", 
       env.getProperty("hibernate.hbm2ddl.auto")); 
     properties.put("hibernate.hbm2ddl.import_files", 
       env.getProperty("hibernate.hbm2ddl.import_files")); 
     em.setJpaPropertyMap(properties); 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(em.getObject()); 
     return em; 
    } 

    @Primary 
    @Bean(name = "transactionManager") 
    public PlatformTransactionManager transactionManager() { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(prodEntityManager().getObject()); 
     return transactionManager; 
    } 

    @Bean 
    public SessionFactory sessionFactory(EntityManagerFactory factory) { 
     if(factory.unwrap(SessionFactory.class) == null){ 
      throw new NullPointerException("factory is not a hibernate factory"); 
     } 
     return factory.unwrap(SessionFactory.class); 
    } 

} 

hibernate.properties

hibernate.connection.driver_class=org.h2.Driver 
hibernate.connection.url=jdbc:h2:~/test 
hibernate.dialect=org.hibernate.dialect.H2Dialect 
hibernate.query.factory_class=org.hibernate.hql.classic.ClassicQueryTranslatorFactory 
hibernate.username=sa 
hibernate.hbm2ddl.auto=create-drop 
hibernate.hbm2ddl.import_files=loadtable.sql 

loadtable.sql

CREATE TABLE CheckedInUsers (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
checkedInEventsId varchar(35), 
checkedInUsersId varchar(35) 
); 
+0

添加將保留一些數據的代碼。 –

+0

已被添加。謝謝 – numerical25

+0

另外,添加h2的配置.. –

回答

0

問題是你要使用單獨的JPA Entity處理UserEvent之間的關係,這是似乎對我來說不合理,因爲你可以使用getCheckedInEvent()getCheckedInUsers()方法來獲得associa ted事件與User並獲得與Event關聯的所有用戶。所以,如果您完全刪除了CheckedInUsers實體,您的問題將得到解決。

+0

感謝您的回覆。我試過這個,並記住我正在使用內存中的休眠。我只是從CheckedInUser類中刪除了Entity和Table註釋。它仍然給出了相同的。錯誤。 – numerical25

+0

你確定它是內存中沒有嵌入文件或什麼的? –

+0

那麼我創建Separate實體的原因是它爲CheckedInUser構建了表。現在我刪除了表,我得到了錯誤:無法在表CheckedInUsers:未找到數據庫列'id'上創建唯一鍵約束(id)。確保你使用了正確的列名,這取決於正在使用的命名策略(它可能與實體中的屬性名不相同,特別是對於關係類型)' – numerical25

1

我analayzing了您的prntstack:

... 
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "ID"; SQL statement: 
insert into CheckedInUsers (checkedInEventsId, checkedInUsersId) values (?, ?) [23502-191] 
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) 
    at org.h2.message.DbException.get(DbException.java:179) 
    at org.h2.message.DbException.get(DbException.java:155) 
    at org.h2.table.Column.validateConvertUpdateSequence(Column.java:307) 
    at org.h2.table.Table.validateConvertUpdateSequence(Table.java:779) 
    at org.h2.command.dml.Insert.insertRows(Insert.java:151) 
    at org.h2.command.dml.Insert.update(Insert.java:114) 
    at org.h2.command.CommandContainer.update(CommandContainer.java:98) 
    at org.h2.command.Command.executeUpdate(Command.java:258) 
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:160) 
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:146) 
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.e 

,在我看來,真正的問題是在id列房顫你CheckedInUsers實體。事實上,如果你看到你的代碼:

@Entity 
@Table(name = "CheckedInUsers") 
public class CheckedInUsers { 

    private String id; 

    private String checkedInEventsId; 

    private String checkedInUsersId; 

    @Id 
    @GeneratedValue(generator="uuid") 
    @GenericGenerator(name = "uuid", strategy = "uuid2") 
    @Column(name = "id", unique = true) 
    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    @Column(name = "checkedInEventsId") 
    public String getEvent() { 
     return checkedInEventsId; 
    } 

    public void setEvent(String event) { 
     this.checkedInEventsId = event; 
    } 

    @Column(name = "checkedInUsersId") 
    public String getUser() { 
     return checkedInUsersId; 
    } 

    public void setUser(String user) { 
     this.checkedInUsersId = user; 
    } 
} 

和你的SQL進行creatig表:

CREATE TABLE CheckedInUsers (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
checkedInEventsId varchar(35), 
checkedInUsersId varchar(35) 
); 

我發現你宣佈Java中的id屬性爲字符串,並以SQL作爲int與自動增量策略。我認爲問題在這裏。

現在我不太瞭解您的域名,但嘗試使您的Java代碼中的數據類型在SQL中相同。

我看到了代碼,我發現你使用SpringData,如果id爲null,spring數據會創建一個新對象,如果id不爲null,則會更新該對象,但是我知道JPA存在一個策略, id爲實體而不是字符串。我從代碼中讀到,你希望你的字符串有id,我可以建議查看mongo使用的spring數據的實現,因爲對於mongo,id生成的默認策略使用uuid。

我希望這可以幫助你