1

有人可以告诉我为什么我会得到 java.sql.SQLException: This function is not supported using HSQL and Spring?我正在尝试在我的数据库中插入一个新行..

下面是我的 DAO,我在 mySession.save(message) 行收到错误:

@Transactional
@Repository
public class MessageDaoImpl implements MessageDao
{


    private Log log = null;
    @Autowired
    private SessionFactory sessionFactory;

    public MessageDaoImpl()
    {
        super();
        log = LogFactory.getLog(MessageDaoImpl.class);

    }

    @SuppressWarnings("unchecked")
    @Transactional(readOnly = true, propagation = Propagation.REQUIRED)
    public List<Message> listMessages()
    {
        try
        {
            return (List<Message>) sessionFactory.getCurrentSession()
                    .createCriteria(Message.class).list();

        } catch (Exception e)
        {
            log.fatal(e.getMessage());
            return null;
        }
    }


    @SuppressWarnings("unchecked")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public void SaveOrUpdateMessage(Message message)
    {
        try
        {
            Session mySession = sessionFactory.getCurrentSession();
            mySession.save(message);
            mySession.flush();
        } catch (Exception e)
        {
            log.fatal(e.getMessage());
        }
    }


}

这是我的主要课程:

public static void main(String[] args)
    {
        ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfig.class);


        MessageService mService  = context.getBean(MessageService.class);

        HelloWorld helloWorld = context.getBean(HelloWorld.class);

        /**
         * Date:   4/26/13 / 9:26 AM
         * Comments:
         *
         *    I added Log4J to the example.
         */

        LOGGER.debug("Message from HelloWorld Bean: " + helloWorld.getMessage());

        Message message = new Message();
        message.setMessage(helloWorld.getMessage());
        //
        mService.SaveMessage(message);



        helloWorld.setMessage("I am in Staten Island, New York");


        LOGGER.debug("Message from HelloWorld Bean: " + helloWorld.getMessage());
    }
}

这是我的数据库配置:

public class DatabaseConfig
{

    private static final Logger LOGGER = getLogger(DatabaseConfig.class);


    @Autowired
    Environment env;

    @Bean
    public DataSource dataSource() {

        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).
        addScript("schema.sql").build();

        return db;
    }


    @Bean
    public DataSource hsqlDataSource()  {

        BasicDataSource ds = new BasicDataSource();


        try {
            ds.setDriverClassName("org.hsqldb.jdbcDriver");
            ds.setUsername("sa");
            ds.setPassword("");
            ds.setUrl("jdbc:hsqldb:mem:mydb");
        }
        catch (Exception e)
        {
            LOGGER.error(e.getMessage());
        }
        return ds;



    }

    @Bean
    public SessionFactory sessionFactory()
    {

        LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
        factoryBean.setDataSource(hsqlDataSource());
        factoryBean.setHibernateProperties(getHibernateProperties());
        factoryBean.setPackagesToScan(new String[]{"com.xxxxx.HelloSpringJavaBasedJavaConfig.model"});

        try
        {
            factoryBean.afterPropertiesSet();
        } catch (IOException e)
        {
            LOGGER.error(e.getMessage());
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }


        return factoryBean.getObject();
    }

    @Bean
    public Properties getHibernateProperties()
    {
        Properties hibernateProperties = new Properties();

        hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
        hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        hibernateProperties.setProperty("hibernate.use_sql_comments", env.getProperty("hibernate.use_sql_comments"));
        hibernateProperties.setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
        hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));

        hibernateProperties.setProperty("hibernate.generate_statistics", env.getProperty("hibernate.generate_statistics"));

        hibernateProperties.setProperty("javax.persistence.validation.mode", env.getProperty("javax.persistence.validation.mode"));

        //Audit History flags
        hibernateProperties.setProperty("org.hibernate.envers.store_data_at_delete", env.getProperty("org.hibernate.envers.store_data_at_delete"));
        hibernateProperties.setProperty("org.hibernate.envers.global_with_modified_flag", env.getProperty("org.hibernate.envers.global_with_modified_flag"));

        return hibernateProperties;
    }

    @Bean
    public HibernateTransactionManager hibernateTransactionManager()
    {
        HibernateTransactionManager htm = new HibernateTransactionManager();
        htm.setSessionFactory(sessionFactory());
        htm.afterPropertiesSet();
        return htm;
    }


}

这就是我要进入控制台的内容:

Exception in thread "main" org.hibernate.AssertionFailure: null id in com.xxx.HelloSpringJavaBasedJavaConfig.model.Message entry (don't flush the Session after an exception occurs)

这是我的消息模型 bean:

@Entity
@Table(name = "messages")
public class Message
{

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private String id;

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

    public String getId()
    {
        return id;
    }

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

    public String getMessage()
    {
        return message;
    }

    public void setMessage(String message)
    {
        this.message = message;
    }

    @Override
    public String toString()
    {
        return "Message{" +
                "id='" + id + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}
4

5 回答 5

10

这与使用的 hsql 版本有关,可能导致问题的版本是 1.8 和 hibernate 4。需要改用 2.2.9

于 2013-07-29T14:22:56.777 回答
1

将hibernate升级到4.2.8版后我遇到了同样的问题。查看日志,我注意到hibernate生成的sql查询试图插入一条主键为空的记录。该字段仅使用以下注释:@Id @GeneratedValue

就像丹尼斯说的一样,将 hsqldb 升级到 2.2.9 版本使这个消失了,我非常感谢他的回复。

于 2014-04-11T18:16:55.140 回答
1

您不能将Stringwith@GenerateValue与 Strategy一起使用,GenerationType.AUTO因为它使用序列生成器,并且不能与非数字值一起使用。你必须自己设置。如果您希望为您生成它,请使用Integer或。Long

休眠文档

或者使用使用字符串值的 id 生成器

@Id 
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")
于 2013-04-26T16:37:16.610 回答
1

这是一个版本问题。我更新了版本,现在一切正常

于 2013-04-29T12:35:28.340 回答
0

这个问题似乎很可能与尝试使用已经发出错误信号的 Session 有关。正如 Sotirios 所提到的,在 DAO 中捕获异常是一个坏主意,如果这样做,重新抛出它们至关重要。

通常,一旦捕获到 Hibernate 异常,您必须回滚事务并关闭会话,因为会话状态可能不再有效(Hibernate 核心文档)。

如果 Session 抛出异常,包括任何 SQLException,立即回滚数据库事务,调用 Session.close() 并丢弃 Session 实例。Session 的某些方法不会使会话保持一致状态。Hibernate 抛出的任何异常都不能被视为可恢复的。通过在 finally 块中调用 close() 确保 Session 将被关闭。

由于您使用的是 Spring,因此其中大部分不适用于您,但您看到的异常消息表明问题的实际原因可能与捕获异常然后继续使用同一会话有关。

于 2013-04-26T21:09:15.927 回答