title: Treat empty string in JoinColumn as null
body: <p>I'm currently working on a project with the following scheme:    </p>
  
  <pre><code>Profile
  -------
  CODE          |  CHAR(6)
  CODE_FUNCTION |  CHAR(2)
  
  Function
  --------
  CODE          |  CHAR(2)
  </code></pre>
  
  <p>The most important part here is the foreign key from <code>Profile</code> to <code>Function</code> (<code>CODE_FUNCTION</code> => <code>CODE</code>).</p>
  
  <p>However, not each profile has a function, so in some cases the CODE_FUNCTION is just a blank row (<code>"  "</code>).</p>
  
  <p>I mapped the function (in <code>Profile</code>) by using:</p>
  
  <pre class="lang-java prettyprint-override"><code>@OneToOne
  @JoinColumn(name = "CODE_FUNCTION", referencedColumnName = "CODE")
  private Function function;
  </code></pre>
  
  <p>And in the <code>Function</code> table the code is mapped by using:</p>
  
  <pre class="lang-java prettyprint-override"><code>@Id
  @Column(name = "CODE_FUNCTION")
  private String code;
  </code></pre>
  
  <p>This is working properly when the profile has a function, however, the moment the function code is not entered, I'm getting the following error:</p>
  
  <pre><code>Caused by: javax.persistence.EntityNotFoundException: Unable to find org.example.entities.Function with id   
      at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:181)
      at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:218)
      at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274)
      at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150)
      at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070)
      at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:989)
      at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:716)
      at org.hibernate.type.EntityType.resolve(EntityType.java:502)
      at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170)
      at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
      at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1114)
      at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
      at org.hibernate.loader.Loader.doQuery(Loader.java:920)
      at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
      at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:324)
      at org.hibernate.loader.Loader.loadEntity(Loader.java:2148)
      at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:78)
      at org.hibernate.loader.entity.EntityLoader.loadByUniqueKey(EntityLoader.java:161)
      at org.hibernate.persister.entity.AbstractEntityPersister.loadByUniqueKey(AbstractEntityPersister.java:2385)
      at org.hibernate.type.EntityType.loadByUniqueKey(EntityType.java:767)
      at org.hibernate.type.EntityType.resolve(EntityType.java:505)
      at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170)
      at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
      at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1114)
      at org.hibernate.loader.Loader.processResultSet(Loader.java:972)
      at org.hibernate.loader.Loader.doQuery(Loader.java:920)
      at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
      at org.hibernate.loader.Loader.doList(Loader.java:2553)
      at org.hibernate.loader.Loader.doList(Loader.java:2539)
      at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
      at org.hibernate.loader.Loader.list(Loader.java:2364)
      at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:496)
      at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387)
      at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:231)
      at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1264)
      at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103)
      at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
      at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:606)
      at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
      at com.sun.proxy.$Proxy77.getResultList(Unknown Source)
      at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:96)
      at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:61)
      at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:96)
      at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:86)
      at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:337)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
      ... 92 more
  </code></pre>
  
  <p>The problem here (I assume) is that, because we're using an empty string (in stead of NULL`), the mapping is failing becasue it's trying to find the function with that ID.</p>
  
  <p>Is there a way to prevent this from happening without adjusting all table records and replacing these empty strings by <code>NULL</code>?
  For example, I know I can use entity listeners to process certain fields, but can I do the same for fields annotated with <code>@JoinColumn</code>?</p>