Как настроить источник данных при создании Hibernate SessionFactory? - PullRequest
18 голосов
/ 10 декабря 2010

Я создаю 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();

Ответы [ 8 ]

14 голосов
/ 10 декабря 2010

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

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

Чтобы использовать пользовательский экземпляр DataSource, используйте InjectedDataSourceConnectionProvider и вставьте в него экземпляр 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);
    }
}

Вы также можетеextend UserSuppliedConnectionProvider .

В соответствии с контрактом ConnectionProvider

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

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

Configuration cfg = new Configuration();
Properties props = new Properties();
props.put( Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName() );
cfg.addProperties(props);
11 голосов
/ 09 октября 2014

Если у вас есть 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 голосов
/ 01 июня 2015

Ответ Луиджи Мендосы - это то, почему мой поиск отправил меня сюда, но я полагаю, что должен дать свою версию, потому что я потратил довольно много времени на поиски, как это сделать - она ​​настраивает ее с базой данных 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>
2 голосов
/ 10 декабря 2010

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

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

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

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

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

1 голос
/ 24 января 2015

Если вы реализовали класс с 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();
        ...
    }
}
1 голос
/ 10 декабря 2010

Если вы используете Spring Framework, используйте 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>
1 голос
/ 10 декабря 2010

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

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

0 голосов
/ 26 декабря 2017

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

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

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

Работает с Hibernate 5.2.9 Final.

...