How can I set Datasource when I'm creating Hibernate SessionFactory?

后端 未结 8 385
星月不相逢
星月不相逢 2020-12-02 17:17

I\'m creating SessionFactory and I have my datasource as object in code where I\'m creating SessionFactory, but i cannot set datasource to Hibernate Configuration object. So

相关标签:
8条回答
  • 2020-12-02 17:58

    I don't think you can. The Hibernate API will let you configure the JDBC properties so that it can manage the connections itself, or you can give it a JNDI DataSource location so it can go and fetch it, but I don't think you can give it a DataSource.

    On the off-chance that you're using Spring, it's easier - use LocalSessionFactoryBean to configure Hibernate, and inject your DataSource into that. Spring performs the necessary magic in the background.

    0 讨论(0)
  • 2020-12-02 17:59

    If you've implemented a class with javax.sql.DataSource, Hibernate's DataSource can be set by configuring properties.

    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();
            ...
        }
    }
    
    0 讨论(0)
  • 2020-12-02 18:05

    If your datasource is bounded at the JNDI tree:

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

    Otherwise, if you have a DataSource object in code, which you want to use:

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

    I would recommend the first one, to let Hibernate handle the connection lifecycle as needed. At the second approach, make sure that you close the connection when it's no longer needed.

    0 讨论(0)
  • 2020-12-02 18:08

    To supply JDBC connections to Session, you need an implementation of ConnectionProvider.

    By default, Hibernate uses DatasourceConnectionProvider which obtains a DataSource instance from JNDI.

    To use a custom DataSource instance, use InjectedDataSourceConnectionProvider and inject the DataSource instance into it.

    There is TODO note on InjectedDataSourceConnectionProvider

    NOTE : setDataSource(javax.sql.DataSource) must be called prior to configure(java.util.Properties).

    TODO : could not find where setDataSource is actually called. Can't this just be passed in to configure???

    As per the note, call setDataSource() method from configure() method.

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

    You can also extend UserSuppliedConnectionProvider.

    According to the contract of ConnectionProvider

    Implementors should provide a public default constructor.

    Hibernate will invoke this constructor if custom ConnectionProvider is set through Configuration instance.

    Configuration cfg = new Configuration();
    Properties props = new Properties();
    props.put( Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName() );
    cfg.addProperties(props);
    
    0 讨论(0)
  • 2020-12-02 18:14

    Luiggi Mendoza's answer is why my search sent me here, but I figure I should give my version because I spent quite some time looking around for how to do this - it sets it up with the Spring in-memory database for testing, a SessionContext and the hbm.xml in case you're not using 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;
        }
    
    }
    

    and you'll need these:

    <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>
    
    0 讨论(0)
  • 2020-12-02 18:19

    If you are using Spring framework, then use LocalSessionFactoryBean for injecting your data source to 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>
    
    0 讨论(0)
提交回复
热议问题