2015-12-19 64 views
-1

我有一個應用程序(使用註釋的Spring 4 MVC + Hibernate 4 + MySQL + Maven集成示例),將Spring與Hibernate結合使用基於註釋的配置。JPA @JoinColumn無法正常工作

我有這樣的表

CREATE TABLE `t_device_event` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `device_event_lat` float(10,6) DEFAULT NULL, 
    `device_event_lng` float(10,6) DEFAULT NULL, 
    `device_id` int(11) unsigned NOT NULL, 
    `device_event_message` varchar(100) DEFAULT NULL, 
    `device_event_received` TIMESTAMP , 
    `coordinates` point NULL, 
    `version` int(11) NULL, 
    PRIMARY KEY (`id`), 
    KEY `device_id` (`device_id`), 
    CONSTRAINT `t_device_event_ibfk_1` FOREIGN KEY (`device_id`) REFERENCES `t_device` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

CREATE TABLE `t_device` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `device_key` varchar(50) DEFAULT NULL, 
    `device_type` varchar(50) DEFAULT NULL, 
    `device_desc` varchar(100) DEFAULT NULL, 
    `application_id` int(11) unsigned NOT NULL, 
    `version` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `application_id` (`application_id`), 
    CONSTRAINT `t_device_ibfk_1` FOREIGN KEY (`application_id`) REFERENCES `t_application` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; 

此域對象:

@Entity 
@Table(name = "t_device") 
@NamedQueries(value = { @NamedQuery(name = "Device.findByKey", 
            query = "from Device as d where d.key = :key") }) 
public class Device implements Serializable { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -7176158728352557756L; 

    private static final Long DEFAULT_VERSION = new Long(0); 

    enum Type { 
     ANDROID, IOS 
    } 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @Column(name = "device_key", unique = true, nullable = false) 
    private String key; 

    @Column(name = "device_desc") 
    private String desc; 

    @Enumerated(EnumType.STRING) 
    @Column(name = "device_type") 
    private Type type; 

    @OneToOne(fetch = FetchType.EAGER) 
    @JoinColumn(name = "application_id", 
       referencedColumnName = "id") 
    private Application application; 

    @Version 
    @Column(name = "version") 
    private Long version = DEFAULT_VERSION; 

    /** 
    * Instantiates a new device. 
    */ 
    public Device() { 
     super(); 
    } 

    /** 
    * Instantiates a new device. 
    * 
    * @param key 
    *   the key 
    */ 
    public Device(final String key) { 
     super(); 
     this.key = key; 
    } 

    /** 
    * Gets the id. 
    * 
    * @return the id 
    */ 
    public Long getId() { 
     return id; 
    } 

    /** 
    * Sets the id. 
    * 
    * @param id 
    *   the new id 
    */ 
    public void setId(final Long id) { 
     this.id = id; 
    } 

    /** 
    * Gets the key. 
    * 
    * @return the key 
    */ 
    public String getKey() { 
     return key; 
    } 

    /** 
    * Sets the key. 
    * 
    * @param key 
    *   the new key 
    */ 
    public void setKey(final String key) { 
     this.key = key; 
    } 

    /** 
    * Gets the desc. 
    * 
    * @return the desc 
    */ 
    public String getDesc() { 
     return desc; 
    } 

    /** 
    * Sets the desc. 
    * 
    * @param desc 
    *   the new desc 
    */ 
    public void setDesc(final String desc) { 
     this.desc = desc; 
    } 

    /** 
    * Gets the type. 
    * 
    * @return the type 
    */ 
    public Type getType() { 
     return type; 
    } 

    /** 
    * Sets the type. 
    * 
    * @param p_type 
    *   the new type 
    */ 
    public void setType(final Type p_type) { 
     type = p_type; 
    } 

    /** 
    * Gets the application. 
    * 
    * @return the application 
    */ 
    public Application getApplication() { 
     return application; 
    } 

    /** 
    * Sets the application. 
    * 
    * @param application 
    *   the new application 
    */ 
    public void setApplication(final Application application) { 
     this.application = application; 
    } 

    /** 
    * Gets the version. 
    * 
    * @return the version 
    */ 
    public Long getVersion() { 
     return version; 
    } 

    /** 
    * Sets the version. 
    * 
    * @param p_version 
    *   the new version 
    */ 
    public void setVersion(final Long p_version) { 
     version = p_version; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see com.yaptechnology.jpa.domain.BaseEntity#equals(java.lang.Object) 
    */ 
    @Override 
    public boolean equals(final Object p_obj) { 
     boolean isEquals = false; 

     try { 
      final Device device = (Device) p_obj; 
      final EqualsBuilder eb = new EqualsBuilder(); 

      eb.append(getKey(), device.getKey()); 
      eb.append(getDesc(), device.getDesc()); 
      eb.append(getType(), device.getType()); 

      isEquals = eb.isEquals(); 
     } catch (final Exception e) { 
      isEquals = false; 
     } 

     return isEquals; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see com.yaptechnology.jpa.domain.BaseEntity#hashCode() 
    */ 
    @Override 
    public int hashCode() { 
     final HashCodeBuilder hcb = new HashCodeBuilder(); 
     hcb.append(getKey()); 
     hcb.append(getDesc()); 
     hcb.append(getType()); 

     return hcb.toHashCode(); 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see com.yaptechnology.jpa.domain.BaseEntity#toString() 
    */ 
    @Override 
    public String toString() { 
     ToStringBuilder tsb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE); 

     tsb.append("id", getId()); 
     tsb.append("key", getKey()); 
     tsb.append("desc", getDesc()); 
     tsb.append("type", getType()); 
     tsb.append("version", getVersion()); 

     return tsb.toString(); 
    } 

} 

此其它之一:

@Entity 
@Table(name = "t_device_event") 
public class DeviceEvent { 

    private static final Long DEFAULT_VERSION = new Long(0); 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 

    @ManyToOne 
    @JoinColumn(name = "device_id") 
    private Device device; 

    @Column(name = "device_event_received") 
    private Long received; 

    @Column(name = "device_event_message") 
    private String message; 

    @Version 
    @Column(name = "version") 
    private Long version = DEFAULT_VERSION; 

    @Embedded 
    private Coordinates coordinates; 

    /** 
    * Instantiates a new device event. 
    * 
    * @param device 
    *   the device 
    */ 
    public DeviceEvent(final Device device) { 
     super(); 
     this.device = device; 
    } 

    /** 
    * Gets the coordinates. 
    * 
    * @return the coordinates 
    */ 
    public Coordinates getCoordinates() { 
     return coordinates; 
    } 

    /** 
    * Sets the coordinates. 
    * 
    * @param coordinates 
    *   the new coordinates 
    */ 
    public void setCoordinates(final Coordinates coordinates) { 
     this.coordinates = coordinates; 
    } 

    /** 
    * Gets the id. 
    * 
    * @return the id 
    */ 
    public Long getId() { 
     return id; 
    } 

    /** 
    * Sets the id. 
    * 
    * @param id 
    *   the new id 
    */ 
    public void setId(final Long id) { 
     this.id = id; 
    } 

    /** 
    * Gets the device. 
    * 
    * @return the device 
    */ 
    public Device getDevice() { 
     return device; 
    } 

    /** 
    * Sets the device. 
    * 
    * @param device 
    *   the new device 
    */ 
    public void setDevice(final Device device) { 
     this.device = device; 
    } 

    /** 
    * Gets the received. 
    * 
    * @return the received 
    */ 
    public Long getReceived() { 
     return received; 
    } 

    /** 
    * Sets the received. 
    * 
    * @param received 
    *   the new received 
    */ 
    public void setReceived(final Long received) { 
     this.received = received; 
    } 

    /** 
    * Gets the message. 
    * 
    * @return the message 
    */ 
    public String getMessage() { 
     return message; 
    } 

    /** 
    * Sets the message. 
    * 
    * @param message 
    *   the new message 
    */ 
    public void setMessage(final String message) { 
     this.message = message; 
    } 

    /** 
    * Gets the version. 
    * 
    * @return the version 
    */ 
    public Long getVersion() { 
     return version; 
    } 

    /** 
    * Sets the version. 
    * 
    * @param p_version 
    *   the new version 
    */ 
    public void setVersion(final Long p_version) { 
     version = p_version; 
    } 


    /* 
    * (non-Javadoc) 
    * 
    * @see com.yaptechnology.jpa.domain.BaseEntity#equals(java.lang.Object) 
    */ 
    @Override 
    public boolean equals(final Object p_obj) { 
     boolean isEquals = false; 

     try { 
      final DeviceEvent deviceEvent = (DeviceEvent) p_obj; 
      final EqualsBuilder eb = new EqualsBuilder(); 

      eb.append(getReceived(), deviceEvent.getReceived()); 
      eb.append(getMessage(), deviceEvent.getMessage()); 
      eb.append(getDevice(), deviceEvent.getDevice()); 

      isEquals = eb.isEquals(); 
     } catch (final Exception e) { 
      isEquals = false; 
     } 

     return isEquals; 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see com.yaptechnology.jpa.domain.BaseEntity#hashCode() 
    */ 
    @Override 
    public int hashCode() { 
     final HashCodeBuilder hcb = new HashCodeBuilder(); 
     hcb.append(getReceived()); 
     hcb.append(getMessage()); 
     hcb.append(getDevice()); 

     return hcb.toHashCode(); 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see com.yaptechnology.jpa.domain.BaseEntity#toString() 
    */ 
    @Override 
    public String toString() { 
     ToStringBuilder tsb = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE); 

     tsb.append("id", getId()); 
     tsb.append("received", getReceived()); 
     tsb.append("message", getMessage()); 
     tsb.append("device", getDevice()); 
     tsb.append("coordinates", getCoordinates()); 
     tsb.append("version", getVersion()); 

     return tsb.toString(); 
    } 

} 

這個控制器:

Device device = deviceService.findByKey("de305d54-75b4-431b-adb2-eb6b9e546014"); 

     LOGGER.debug("device: {}", device); 

     DeviceEvent deviceEvent = new DeviceEvent(device); 
     deviceEvent.setCoordinates(new Coordinates((double)30.8340150, (double)2.3778850)); 
     deviceEvent.setMessage("message"); 
     deviceEventService.save(deviceEvent); 

但是當我保存

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'device_id' cannot be null 
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
    com.mysql.jdbc.Util.handleNewInstance(Util.java:404) 
    com.mysql.jdbc.Util.getInstance(Util.java:387) 
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:934) 
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3870) 
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3806) 
    com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2470) 
    com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2617) 
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2550) 
    com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861) 
    com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2073) 
    com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2009) 
    com.mysql.jdbc.PreparedStatement.executeLargeUpdate(PreparedStatement.java:5094) 
    com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1994) 
    org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:204) 
    org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:84) 
    org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:42) 
    org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2792) 
    org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3362) 
    org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81) 
    org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:597) 
    org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:232) 
    org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:213) 
    org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:256) 
    org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:317) 
    org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:272) 
    org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:178) 
    org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:109) 
    org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67) 
    org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189) 
    org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132) 
    org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) 
    org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775) 
    org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748) 
    org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753) 
    org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    java.lang.reflect.Method.invoke(Method.java:606) 
    org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:293) 
    com.sun.proxy.$Proxy107.persist(Unknown Source) 
    fr.telecom.dao.impl.AbstractDao.persist(AbstractDao.java:91) 
    fr.telecom.service.impl.DeviceEventServiceImpl.save(DeviceEventServiceImpl.java:25) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    java.lang.reflect.Method.invoke(Method.java:606) 
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) 
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) 
    com.sun.proxy.$Proxy112.save(Unknown Source) 
    fr.telecom.controller.AppController.listDevices(AppController.java:63) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    java.lang.reflect.Method.invoke(Method.java:606) 
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) 
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) 
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) 
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:624) 
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:731) 
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:118) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
+0

它在構造函數中完成:DeviceEvent deviceEvent = new DeviceEvent(device); –

+0

我不這麼認爲......爲什麼? –

+0

對不起,只是閱讀代碼並尋找通常的錯誤。 –

回答

1

的設備需要以使FK可以插入到device_event表首先保存我得到這個錯誤。您可以通過添加如下的級聯選項來讓框架爲您做到這一點。

@ManyToOne(cascade = CascadeType.ALL) 
@JoinColumn(name = "device_id") 
private Device device;