web-dev-qa-db-fra.com

Comment définir une source de données lorsque je crée Hibernate SessionFactory?

Je crée SessionFactory et ma source de données est un objet de code dans lequel je crée SessionFactory, mais je ne peux pas définir de source de données sur l'objet Configuration Hibernate. Alors, comment puis-je définir ma source de données sur ma 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();
18
newbie

Pour fournir des connexions JDBC à Session, vous avez besoin d'une implémentation de ConnectionProvider .

Par défaut, Hibernate utilise DatasourceConnectionProvider qui obtient une instance DataSource de JNDI.

Pour utiliser une instance DataSource personnalisée, utilisez InjectedDataSourceConnectionProvider et injectez-y l'instance DataSource.

Il y a note TODO sur InjectedDataSourceConnectionProvider

REMARQUE : setDataSource (javax.sql.DataSource) doit être appelé avant configure (Java.util.Properties).

TODO: impossible de trouver où setDataSource est en fait appelée . Cela ne peut-il pas simplement être transmis à configurer ???

Conformément à la remarque, appelez la méthode setDataSource() à partir de la méthode 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);
    }
}

Vous pouvez également étendre UserSuppliedConnectionProvider .

Selon le contrat de ConnectionProvider 

Les développeurs devraient fournir un public constructeur par défaut.

Hibernate appellera ce constructeur si ConnectionProvider personnalisé est défini via l'instance de configuration.

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

Si vous avez votre DataSource stockée dans JNDI, utilisez simplement:

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

Mais si vous utilisez un fournisseur de source de données personnalisé tel qu'Apache DBCP ou BoneCP et vous ne souhaitez pas utiliser un framework d'injection de dépendances tel que Spring , vous pouvez l'injecter dans StandardServiceRegistryBuilder avant de créer 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());

Notez que si vous utilisez cette approche, vous n'avez plus besoin de mettre les paramètres de connexion dans votre fichier hibernate.cfg.xml. Voici un exemple de fichier compatible hibernate.cfg.xml lorsqu’on utilise l’approche ci-dessus:

<?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>

Code ci-dessus testé sur Hibernate 4.3.

9
Luiggi Mendoza

La réponse de Luiggi Mendoza est la raison pour laquelle ma recherche m’a envoyé ici, mais je pense que je devrais donner ma version parce que j’ai passé un certain temps à chercher comment faire cela. le fichier hbm.xml au cas où vous n'utiliseriez pas d'annotations:

/**
 * 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;
    }

}

et vous aurez besoin de ceux-ci:

<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>
3
Adam

Si votre source de données est liée à l'arborescence JNDI:

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

Sinon, si vous avez un objet DataSource dans le code que vous souhaitez utiliser:

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

Je recommanderais le premier, laisser Hibernate gérer le cycle de vie de la connexion si nécessaire. À la deuxième approche, assurez-vous de fermer la connexion lorsqu'elle n'est plus nécessaire.

2
Tomas Narros

Si vous utilisez la structure Spring, utilisez LocalSessionFactoryBean pour injecter votre source de données dans 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
nIKUNJ

Si vous avez implémenté une classe avec javax.sql.DataSource, vous pouvez définir la DataSource d'Hibernate en configurant les propriétés.

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
user2601995

Je ne pense pas que tu peux. L'API Hibernate vous permettra de configurer les propriétés JDBC de manière à pouvoir gérer les connexions elle-même. Vous pouvez également lui attribuer un emplacement JNDI DataSource afin de pouvoir le récupérer, mais je ne pense pas que vous puissiez donner il une source de données.

Si vous utilisez Spring, c'est plus facile - utilisez LocalSessionFactoryBean pour configurer Hibernate et injectez votre DataSource dans cela. Le printemps effectue la magie nécessaire en arrière-plan.

1
skaffman

J'ai utilisé LocalContainerEntityManagerFactoryBean pour créer une instance EntityManagerFactory dans la classe de configuration.

S'il est nécessaire de définir une autre source de données, il est possible de le mettre à jour avec l'instance de la fabrique du gestionnaire d'entités lors de l'exécution:

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

Cela fonctionne avec Hibernate 5.2.9 Final.

0
user9117214