java.sql.SQLException:使用 HSQL 和 Spring 不支持此函数

Posted

技术标签:

【中文标题】java.sql.SQLException:使用 HSQL 和 Spring 不支持此函数【英文标题】:java.sql.SQLException: This function is not supported using HSQL and Spring 【发布时间】:2013-04-26 16:25:15 【问题描述】:

谁能告诉我为什么我得到 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 + '\'' +
                '';
    

【问题讨论】:

你有一个null id。显示您的 Message 类实现。另外,不要在你的 daos 中捕获异常。 @SotiriosDelimanolis ID 是“@GeneratedValue(strategy = GenerationType.AUTO)”,所以我不必在其中输入值 我刚刚把源码贴在github上,大家可以试试 我没有访问权限。不要那样做,在这里发布您的代码或错误。 【参考方案1】:

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

【讨论】:

【参考方案2】:

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

Hibernate docs

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

@Id 
@GeneratedValue(generator="system-uuid")
@GenericGenerator(name="system-uuid", strategy = "uuid")

【讨论】:

这不是问题,但我在 github 上发布了源代码,您可以尝试一下 @SJS 告诉你这不是问题所在?【参考方案3】:

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

【讨论】:

【参考方案4】:

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

升级 hsqldb 到 2.2.9 版本让这个消失了,就像Denis 说的一样,非常感谢他的回复。

【讨论】:

【参考方案5】:

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

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

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

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

【讨论】:

以上是关于java.sql.SQLException:使用 HSQL 和 Spring 不支持此函数的主要内容,如果未能解决你的问题,请参考以下文章

java.sql.SQLException:使用 HSQL 和 Spring 不支持此函数

java.sql.SQLException:用户'root'@'localhost'的访问被拒绝(使用密码:是)

“java.sql.SQLException:用户'root'@'localhost'的访问被拒绝(使用密码:YES)”

运行:java.sql.SQLException:用户'root'@'localhost'的访问被拒绝(使用密码:否)

错误:java.sql.SQLException:用户'root@localhost'@'localhost'的访问被拒绝(使用密码:是)

Phpstorm 数据库:java.sql.SQLException:通信链接失败