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();
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);
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.
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>
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.
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>
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();
...
}
}
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.
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.