如何从 java 开始 H2

How to start H2 from java

我有一个连接到 H2 并使用休眠做一些事情的小应用程序。我已经成功地使 H2 和 Hibernate 一起工作,但我的问题是我必须手动启动 H2,这需要以编程方式完成。我尝试了几件事,但 none 有效。

我试过这个最新的东西

server = Server.createTcpServer("-tcpAllowOthers").start();

我得到这个异常:

java.lang.ExceptionInInitializerError
    at com.runtimeload.HibernateUtil.startH2AndBuildSessionFactory(HibernateUtil.java:26)
    at com.runtimeload.HibernateUtil.<clinit>(HibernateUtil.java:12)
    at com.runtimedataload.RuntimeDataLoadTest.<init>(RuntimeDataLoadTest.java:30)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217)
    at org.junit.runners.BlockJUnit4ClassRunner.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access[=12=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.hibernate.exception.JDBCConnectionException: Error calling Driver#connect
    at org.hibernate.engine.jdbc.connections.internal.BasicConnectionCreator.convert(BasicConnectionCreator.java:122)
    at org.hibernate.engine.jdbc.connections.internal.BasicConnectionCreator.convertSqlException(BasicConnectionCreator.java:140)
    at org.hibernate.engine.jdbc.connections.internal.DriverConnectionCreator.makeConnection(DriverConnectionCreator.java:58)
    at org.hibernate.engine.jdbc.connections.internal.BasicConnectionCreator.createConnection(BasicConnectionCreator.java:75)
    at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl.configure(DriverManagerConnectionProviderImpl.java:106)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:260)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:94)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1887)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1845)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
    at com.wkfsfrc.drools.dummy.runtimeload.HibernateUtil.startH2AndBuildSessionFactory(HibernateUtil.java:21)
    ... 27 more
Caused by: org.h2.jdbc.JdbcSQLException: Wrong user name or password [28000-178]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:344)
    at org.h2.message.DbException.get(DbException.java:178)
    at org.h2.message.DbException.get(DbException.java:154)
    at org.h2.message.DbException.get(DbException.java:143)
    at org.h2.engine.Engine.validateUserAndPassword(Engine.java:316)
    at org.h2.engine.Engine.createSessionAndValidate(Engine.java:150)
    at org.h2.engine.Engine.createSession(Engine.java:125)
    at org.h2.server.TcpServerThread.run(TcpServerThread.java:150)
    at java.lang.Thread.run(Thread.java:745)

所以这是我现有的代码,如果我手动启动 H2 服务器,它可以正常工作:

hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">org.h2.Driver</property>
        <property name="connection.url">jdbc:h2:tcp://localhost/~/test;IFEXISTS=TRUE</property>
        <property name="connection.username">sa</property>
        <property name="connection.password">sa</property>
        <property name="connection.pool_size">5</property>
        <property name="dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="current_session_context_class">thread</property>
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <property name="show_sql">true</property>
        <mapping class="com.runtimeload.Employee"/>
    </session-factory>
</hibernate-configuration>

HibernateUtil.java

package com.runtimeload;

import org.h2.tools.Server;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

import java.sql.Connection;
import java.sql.DriverManager;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = startH2AndBuildSessionFactory();

    public static Server server;

    private static SessionFactory startH2AndBuildSessionFactory() {

        startH2Manually();

        try {
            return new AnnotationConfiguration()
                    .configure()
                    .buildSessionFactory();
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    private static final void startH2Manually() {

        // this is what I have done so for and does not work

        try {
            server = Server.createTcpServer("-tcpAllowOthers").start();

            Thread.sleep(5000);
        }
        catch (Exception e) {
            System.err.println("h2 server failed to start");
        }
    }
}

RuntimeDataLoadTest.java

package com.runtimedataload;

import com.KieSessionFactory;
import com.SessionIDs;
import com.runtimeload.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.kie.api.runtime.KieSession;

import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

    public class RuntimeDataLoadTest {

        SessionFactory sf = HibernateUtil.getSessionFactory();

        private Connection conn;

        @Before
        public void createEnv() throws  Exception{
            Class.forName("org.h2.Driver");
            conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "sa");

            Statement stat = conn.createStatement();

            stat.execute("drop table EMPLOYEE");
            stat.execute("create table EMPLOYEE(id int primary key, firstname varchar(255), lastname varchar(255), cellphone varchar(255));");
            stat.execute("insert into EMPLOYEE values(3, 'aurel', 'ln', 'cp')");


        }

...
   }

不介意测试方法,流口水的制作和抽象

谢谢!

这在我的测试用例中对我有用:

JdbcDataSource ds = new JdbcDataSource();
 ds.setURL("jdbc:h2:mem:test;MODE=Oracle");
 ds.setUser("sa");
 ds.setPassword("sa");
 RunScript.execute(ds.getConnection(), new FileReader("schema.sql"));
 Server server = Server.createWebServer("-webAllowOthers");
 server.start();

希望对您有所帮助。

最终我用一个maven插件启动了H2服务器。您将在下面找到源代码:

            <plugin>
            <groupId>com.btmatthews.maven.plugins.inmemdb</groupId>
            <artifactId>inmemdb-maven-plugin</artifactId>
            <configuration>
                <skip>${skip.unit.tests}</skip>
                <monitorPort>11527</monitorPort>
                <monitorKey>myKey</monitorKey>
                <daemon>true</daemon>
                <type>h2</type>
                <database>${connection.database}</database>
                <username>${connection.username}</username>
                <password>${connection.password}</password>
            </configuration>
            <executions>
                <execution>
                    <id>startH2Server</id>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <phase>process-test-classes</phase>
                </execution>
                <execution>
                    <id>stopH2Server</id>
                    <goals>
                        <goal>stop</goal>
                    </goals>
                    <phase>prepare-package</phase>
                </execution>
            </executions>
        </plugin>

顺便说一句,我需要 h2 用于测试目的...

并且连接 url 需要更改为:

<property name="connection.url">jdbc:h2:tcp://localhost:9092/mem:test</property>

其他属性保持不变。

希望这对其他人有所帮助。干杯!