【问题标题】:Hibernate @SqlInsert annotation getting nulls from bean and not valuesHibernate @SqlInsert 注释从 bean 获取空值而不是值
【发布时间】:2017-08-08 19:50:30
【问题描述】:

我正在尝试使用 jpa + hibernate 和 @SQLInsert 注释插入 mysql 表。 (我一直在尝试更精细的插入查询,直到我意识到基本的插入查询不起作用)。 bean 在下面,entityManager.persist(或 entityManager.merge)上发生了什么,即使我在 bean 上设置了 3 个值,并将它们记录下来,hibernate 抱怨 CKEY 为 NULL

豆子:

import java.io.Serializable;
import java.util.Calendar;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.hibernate.annotations.SQLInsert;

@Entity ( )
@Table ( name = "cachedb" )
@SQLInsert( sql="insert into cachedb ( ckey , cvalue , expiry ) VALUES ( ? , ? , ?  )")
public class CacheDb implements Serializable
{

    private static final long serialVersionUID = 1L;

    @Id ( )
    @Column ( name = "ckey" )
    private String key;

    @Column ( name = "cvalue" )
    private String value;

    @Column ( name = "expiry" )
    private Calendar expiry;

    @SuppressWarnings ( "unused" )
    private CacheDb()
    {
    }

    public CacheDb( final String _key , final String _value )
    {
        this.key = _key;
        this.value = _value;
    }

    public CacheDb( final String _key , final String _value , final int expirtyMinutes )
    {
        this.key = _key;
        this.value = _value;
        final Calendar cal = Calendar.getInstance();
        cal.add( Calendar.MINUTE , expirtyMinutes );
        this.expiry = cal;
    }

    public Calendar getExpiry()
    {
        return this.expiry;
    }

    public void setExpiry( final Calendar _expiry )
    {
        this.expiry = _expiry;
    }

    public static long getSerialversionuid()
    {
        return serialVersionUID;
    }

    public void setKey( final String _key )
    {
        this.key = _key;
    }

    public String getKey()
    {
        return this.key;
    }

    public void setIKey( final String _key )
    {
        this.key = _key;
    }

    public String getValue()
    {
        return this.value;
    }

    public void setValue( final String _value )
    {
        this.value = _value;
    }

    @Override
    public String toString()
    {
        return "CacheDb [key=" + this.key + ", value=" + this.value + ", expiry=" + this.expiry + "]";
    }
}

我用来测试插入的一些示例代码:

import java.util.List;
import javax.persistence.Query;
import com.database.jpa.EntityUtils;

public class TestInsert
{
    public static void main(String[] args) throws Exception 
    {      
        javax.persistence.EntityManager em = null;
        String key = "KEY.TEST.08082017";
        try        
        {
            em = EntityUtils.getEntityManagerWithOutTransaction( "RLENTYMGR" );
            em.getTransaction().begin();
            final Query q = em.createQuery("select p from CacheDb p where key = ?1" );
            q.setParameter( 1 , key );
            final List<CacheDb> resultsList = q.getResultList();
            if (resultsList.size()==0)
            {
                CacheDb newRecord = new CacheDb();
                newRecord.setKey( key ); // only required column varchar(100)
                newRecord.setValue( "TESTB" ); //varchar(1000)   
                //newRecord.setExpiry(null); not needed default is null                 
                em.persist( newRecord );
                //newRecord = em.merge( newRecord );
            }
            em.getTransaction().commit();
        }
        catch(final Exception e)
        {
            e.printStackTrace();
            if (em!=null) 
            {
                em.getTransaction().rollback();
            }
        }
        finally
        {
            if (em!=null) {em.close();}
        }
    }




}

例外:

Caused by: java.sql.BatchUpdateException: Column 'CKEY' cannot be null
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2055)
    at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1467)
    at org.hibernate.engine.jdbc.batch.internal.BatchingBatch.performExecution(BatchingBatch.java:123)

【问题讨论】:

  • 在下面修复/回答

标签: java hibernate jpa


【解决方案1】:

hibernate 似乎不会查看您在@SQLInsert 中使用的列的顺序。

它只使用它自己的顺序——你必须先让 Hibernate 为你生成一个插入语句,然后在你的自定义 @SQLInsert 中模仿它来找出它。

【讨论】:

    【解决方案2】:

    作为@user1889665 stated,hibernate 使用它自己的列顺序,如docs 中所述:

    参数顺序很重要,由 Hibernate 处理属性的顺序定义。您可以通过启用调试日志来查看预期的顺序,因此 Hibernate 可以打印出用于创建、更新、删除实体的静态 SQL。

    要查看预期的顺序,请记住不要通过注释或映射文件包含您的自定义 SQL,因为这将覆盖 Hibernate 生成的静态 SQL。

    基本上你需要这样做:

    • 删除@SQLInsert
    • 启用调试日志记录
      logging.level.org.hibernate=DEBUG
      
    • 正常插入实体
      myCrudRepository.save(myEntity)
      
    • 检查日志以查看生成的插入语句
      org.hibernate.SQL : insert into MY_TABLE (notMyFirstColumn, myLastColumn, myFirstColumn) values (?, ?, ?)
      
    • 使用来自@SQLInsert 日志中打印的插入语句的顺序
      @SQLInsert(sql = "INSERT INTO MY_TABLE(notMyFirstColumn, myLastColumn, myFirstColumn) values (?, ?, ?)")
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多