Подтвердить что ты не робот

Как установить Datasource при создании Hibernate SessionFactory?

Я создаю SessionFactory, и у меня есть свой источник данных как объект в коде, где я создаю SessionFactory, но я не могу установить источник данных для объекта конфигурации Hibernate. Итак, как я могу установить свой источник данных для своего SessionFactory?

Configuration configuration = new Configuration();
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect");
configuration.setProperties(properties);
configuration.setProperty("packagesToScan", "com.my.app");
SessionFactory sessionFactory = configuration.configure().buildSessionFactory();
4b9b3361

Ответ 1

Чтобы предоставить JDBC-соединения для Session, вам нужна реализация ConnectionProvider.

По умолчанию Hibernate использует DatasourceConnectionProvider который получает экземпляр DataSource из JNDI.

Чтобы использовать пользовательский экземпляр DataSource, используйте InjectedDataSourceConnectionProvider и DataSource в него экземпляр DataSource.

На InjectedDataSourceConnectionProvider есть примечание TODO

ПРИМЕЧАНИЕ: setDataSource (javax.sql.DataSource) должен быть вызван до настройки (java.util.Properties).

TODO: не удалось найти, где фактически вызывается setDataSource. Разве это не может быть передано для настройки???

Согласно примечанию, вызовите setDataSource() из метода configure().

public class CustomConnectionProvider extends InjectedDataSourceConnectionProvider {
    @Override
    public void configure(Properties props) throws HibernateException {
        org.apache.commons.dbcp.BasicDataSource dataSource = new BasicDataSource();
        org.apache.commons.beanutils.BeanUtils.populate( dataSource, props );
        setDataSource(dataSource);

        super.configure(props);
    }
}

Вы также можете расширить UserSuppliedConnectionProvider.

Согласно договору ConnectionProvider

Разработчики должны предоставить общедоступный конструктор по умолчанию.

Hibernate вызовет этот конструктор, если пользовательский ConnectionProvider установлен через экземпляр конфигурации.

Configuration cfg = new Configuration();
Properties props = new Properties();
props.put( Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName() );
cfg.addProperties(props);

Ответ 2

Если у вас есть ваш DataSource, хранящийся в JNDI, просто используйте:

configuration.setProperty(
    "hibernate.connection.datasource",
    "java:comp/env/jdbc/yourDataSource");

Но если вы используете собственный поставщик источников данных, такой как Apache DBCP или BoneCP и , вы не хотите использовать инфраструктуру инъекций зависимостей, например Spring, тогда вы можете ввести ее на StandardServiceRegistryBuilder перед созданием SessionFactory:

//retrieve your DataSource
DataSource dataSource = ...;
Configuration configuration = new Configuration()
    .configure();
//create the SessionFactory from configuration
SessionFactory sf = configuration
    .buildSessionFactory(
        new StandardServiceRegistryBuilder()
            .applySettings(configuration.getProperties())
            //here you apply the custom dataSource
            .applySetting(Environment.DATASOURCE, dataSource)
            .build());

Обратите внимание, что если вы используете этот подход, вам больше не нужно устанавливать параметры подключения в свой hibernate.cfg.xml. Вот пример совместимого файла hibernate.cfg.xml при использовании подхода сверху:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
        <property name="show_sql">false</property>
        <!-- your mappings to classes go here -->
    </session-factory>
</hibernate-configuration>

Код выше проверен на Hibernate 4.3.

Ответ 3

Ответ Luiggi Mendoza - вот почему мой поиск отправил меня сюда, но я полагаю, что должен предоставить свою версию, потому что я потратил довольно много времени на то, чтобы узнать, как это сделать - он устанавливает ее с помощью базы данных Spring в памяти тестирование, SessionContext и hbm.xml в случае, если вы не используете аннотации:

/**
 * Instantiates a H2 embedded database and the Hibernate session.
 */
public abstract class HibernateTestBase {

    private static EmbeddedDatabase dataSource;
    private static SessionFactory sessionFactory;
    private Session session;

    @BeforeClass
    public static void setupClass() {
        dataSource = new EmbeddedDatabaseBuilder().
                setType(EmbeddedDatabaseType.H2).
                addScript("file:SQLResources/schema-1.1.sql").
                addScript("file:SQLResources/schema-1.2.sql").
                build();
        Configuration configuration = new Configuration();
        configuration.addResource("hibernate-mappings/Cat.hbm.xml");
        configuration.setProperty("hibernate.dialect",
                "org.hibernate.dialect.Oracle10gDialect");
        configuration.setProperty("hibernate.show_sql", "true");
        configuration.setProperty("hibernate.current_session_context_class",
                "org.hibernate.context.internal.ThreadLocalSessionContext");
        StandardServiceRegistryBuilder serviceRegistryBuilder =
                new StandardServiceRegistryBuilder();
        serviceRegistryBuilder.applySetting(Environment.DATASOURCE, dataSource);
        serviceRegistryBuilder.applySettings(configuration.getProperties());
        StandardServiceRegistry serviceRegistry =
                serviceRegistryBuilder.build();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        sessionFactory.openSession();
    }

    @AfterClass
    public static void tearDown() {
        if (sessionFactory != null) {
            sessionFactory.close();
        }
        if (dataSource != null) {
            dataSource.shutdown();
        }
    }

    @Before
    public final void startTransaction() {
        session = sessionFactory.getCurrentSession();
        session.beginTransaction();
    }

    @After
    public final void rollBack() {
        session.flush();
        Transaction transaction = session.getTransaction();
        transaction.rollback();
    }

    public Session getSession() {
        return session;
    }

}

и вам понадобятся следующие данные:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>4.1.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <version>1.4.184</version>
  <scope>test</scope>
</dependency>

Ответ 4

Если ваш источник данных ограничен в дереве JNDI:

configuration.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test");

В противном случае, если у вас есть объект DataSource в коде, который вы хотите использовать:

java.sql.Connection conn = datasource.getConnection();
Session session = sessionFactory.openSession(conn);

Я бы порекомендовал первый, чтобы Hibernate обрабатывал жизненный цикл соединения по мере необходимости. При втором подходе убедитесь, что вы закрываете соединение, когда оно больше не требуется.

Ответ 5

Я не думаю, что ты можешь. API Hibernate позволит вам настроить свойства JDBC, чтобы он мог управлять самими соединениями, или вы можете предоставить ему местоположение источника данных JNDI, чтобы он мог его вытащить, но я не думаю, что вы можете предоставить ему DataSource.

В случае, если вы используете Spring, проще - используйте LocalSessionFactoryBean для настройки Hibernate и введите в него свой DataSource. Spring выполняет необходимую магию в фоновом режиме.

Ответ 6

Если вы используете фреймворк Spring, используйте LocalSessionFactoryBean для ввода источника данных в Hibernate SessionFactory.

<beans>
    <bean id="YourClass"
        class="com.YourClass.
        <property name="sessionFactory">
            <ref bean="DbSessionFactory" />
        </property>     
    </bean>


    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName">
            <value>org.postgresql.Driver</value>
        </property>
        <property name="url">
            <value>jdbc:postgresql://localhost/yourdb</value>
        </property>
        <property name="username">
            <value>postgres</value>
        </property>
        <property name="password">
            <value>postgres</value>
        </property>     
    </bean>

    <bean id="DbSessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource">
            <ref local="dataSource"/>
        </property>     
        <property name="mappingResources">
            <list>
                <value>conf/hibernate/UserMapping.hbm.xml</value>               
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect"> org.hibernate.dialect.PostgreSQLDialect </prop>      
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.cache.use_second_level_cache"> true </prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
            </props>
        </property>
    </bean>
</beans>

Ответ 7

Если вы внедрили класс с javax.sql.DataSource, Hibernate DataSource можно настроить, настроив свойства.

import javax.sql.DataSource;
public class HibernateDataSource implements DataSource {
    ...
}


import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
public class MyHibernateCfg {
    public void initialize() {
        HibernateDataSource myDataSource = new HibernateDataSource();
        Configuration cfg = new Configuration();
        // this is how to configure hibernate datasource
        cfg.getProperties().put(Environment.DATASOURCE, myDataSource);
        ...
    }
}


import org.hibernate.cfg.Configuration;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
public class TableClass {
    public void initialize() {
        MyHibernateCfg cfg = new MyHibernateCfg();
        Configuration conf = cfg.getCfg();
        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
        SessionFactory sessionFactory = conf.buildSessionFactory(serviceRegistry);
        Session sessionFactory.openSession();
        ...
    }
}

Ответ 8

Я использовал LocalContainerEntityManagerFactoryBean для создания экземпляра EntityManagerFactory в классе конфигурации.

Если требуется установить другой DataSource, то можно обновить его с помощью экземпляра диспетчера сущностей factory во время выполнения:

@Service("myService")
public class MyService
{
....
    @Autowired
    private LocalContainerEntityManagerFactoryBean emf;
....
    public void replaceDataSource(DataSource dataSource)
    {
        emf.setDataSource(dataSource);
        emf.afterPropertiesSet();
    }
....
}

Он работает с Hibernate 5.2.9 Final.