I use Hibernate and Derby.
I have a hibernate.cfg.xml and all I did for working with db waas to get a Session :
return new AnnotationConfiguration().configure( "files/hibernate.cfg.xml" ).buildSessionFactory().getCurrentSession();
my hibernate.cfg.xml containes
<property name="connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property>
<property name="connection.url">jdbc:derby:crmdb;create=true</property>
and some other properties and mappings for entity classes.
now I want to set dataEncryption for derby db and bootPassword at runtime.
I changed hibernate.cfg.xml :
<property name="connection.url">jdbc:derby:crmdb;create=true;dataEncryption=true;bootPassword=myPass</property>
and everything was ok.
Now I want to set bootPassword at runtime, e.x.by reading from an environment variable. that´s the problem!
when I delete "connection.url" from hibernate.cfg.xml and trying to set it inside my code, this error ocurres :
java.lang.UnsupportedOperationException: The application must supply JDBC connections
and if I delete only bootPassword, it can not connect to db.
any idea ?
It resolved !
I should set "hibernate.connection.url" instead of "connection.url" !
You need to modify the configuration before building the sessionFactory:
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory(){
if(sessionFactory==null){
Configuration configuration = new AnnotationConfiguration().configure( "files/hibernate.cfg.xml" );
configuration.setProperty("hibernate.connection.url", "jdbc:derby:crmdb;create=true;dataEncryption=true;bootPassword="+password);
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
}
return sessionFactory;
}
Other remark : you must avoid to recreate a new SessionFactory everytime (it take a lot of time, consume lot of resources and it's useless). i.e. You must create one sessionFactory for each bootPassword (since it's the only dynamic part) and if you only have one bootPassword - i.e. one single DB - then your sessionFactory can/must be a singleton.
ref
Related
I have this peristence.xml that deploys on WildFly:
<persistence-unit name="optaweb-employee-rostering-persistence-unit" transaction-type="JTA">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
...
</persistence-unit>
Now I'd like to reuse it in a plain Java application, with a direct JDBC connection, so without JNDI:
Map<String, String> properties = new HashMap<>();
properties.put("javax.persistence.jdbc.driver", "org.hsqldb.jdbcDriver");
properties.put("javax.persistence.jdbc.url", "jdbc:hsqldb:mem:testdb");
properties.put("javax.persistence.jdbc.user", "sa");
properties.put("javax.persistence.jdbc.password", "");
// Overwrites transaction-type successfully
properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
// TODO overwrite jta-data-source
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(
"optaweb-employee-rostering-persistence-unit", properties);
How do I overwrite jta-data-source?
I've tried a number of JPA properties to override jta-data-source, with no success:
// Overwrites jta-data-source
// but triggers a JNDI lookup of "" which crashes of course
properties.put("javax.persistence.jtaDataSource", "");
// Does not overwrite jta-data-source
properties.put("javax.persistence.jtaDataSource", null);
// Does not overwrite jta-data-source
properties.put("javax.persistence.nonJtaDataSource", "foo");
I've also tried a number of hibernate specific properties, such as hibernate.transaction.coordinator_class and hibernate.connection.datasource with the same failing results as above.
As far as I can tell from the source of Hibernate ORM (in particular org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl#EntityManagerFactoryBuilderImpl(org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor, java.util.Map, java.lang.ClassLoader, org.hibernate.boot.registry.classloading.spi.ClassLoaderService)), these particular JPA settings override settings from hibernate.properties or from the Map you will provide to Persistence.createEntityManagerFactory.
It may be a dumb idea, but can't you just do the opposite, i.e. not set the datasource in your persistence unit, but set it through a hibernate.properties file in your WildFly application? Then you can do whatever you want in your plain java application.
I am trying to enable my web application to use one (MySQL) schema per user.
I am using Spring with JPA along with Hibernate.
Is the Hibernate Multi-tenancy concept relevant?
The way I am trying to do it is
(a) have a EntityManagerFactory per HTTPSession and
(b) set the schema in it at login.
I have figured out how to do (b), but I still have issues doing (a).
I tried putting #Scope(WebApplicationContext.SCOPE_SESSION), but what about the global EntityManagerFactory?
Any help?
You can implement your own ConnectionProvider and there make extra settings.
But I think that you have large problems with the architecture your application if you want to do one schema per user.
UPD1
If you use spring. You can try to declare a bean with own impl of ConnectionProvider in Session scope.
But there is a big problem. Hibernate make the ConnectionProvider. It means that you have to impl own ServiceRegistry (with working through Spring) and override StandardServiceRegistryBuilder, and impl EntityManagerFactoryBuilder (based on EntityManagerFactoryBuilderImpl but with your StandardServiceRegistryBuilder).
When new session have been created it'll use ConnectionProvider to create the connection (Probably you'll have to override some classes).
This is really not suggested.. This will harm you later, you can't do differnt schema for diffrent user. You can always create you own properties to the connection..
Configuration cfg = new Configuration();
cfg.configure();
System.setProperty("hibernate.connection.password",pass);
System.setProperty("hibernate.connection.username",usr);
System.setProperty("hibernate.connection.driver_class", driver_class);
System.setProperty("hibernate.connection.url", driver_url);
System.setProperty("hibernate.dialect", dialect);
// etc, etc, for all properties
cfg.setProperties(System.getProperties());
sessionFactory = cfg.buildSessionFactory();
It can be something like that.. But this is WRONG!
I have to configure two database on same project by configuring two CFG file,
I tried but it is always use the first configuration file,
May i know how can i use two database on same project
In your code, what you need to do is to open two different session factory for different databases.
For example:
Configuration configA=new Configuration();//use the default hibernate.cgf.xml file
Congiruration configB=new Configuration.configure('/hibernate_db2.cfg.xml') // use hibernate_db2.cfg.xml under root folder.
SessionFactory sfa=configA.buildSessionFactory();
SessionFactory sfb=configB.buildSessionFactory();
Now, you open different session using different db.
You need to have two configuration files.
hibernate-mysql.cfg.xml
hibernate-oracle.cfg.xml
And code should be like this.
mysql configuration
private static SessionFactory sessionAnnotationFactory;
sessionAnnotationFactory = new Configuration().configure("hibernate-mysql.cfg.xml").buildSessionFactory();
Session session = sessionAnnotationFactory.openSession();
oracle sql configuration
sessionAnnotationFactory = new Configuration().configure("hibernate-oracle.cfg.xml").buildSessionFactory();
Session session = sessionAnnotationFactory.openSession()
I'd like to provide the ability to completely wipe my webapp's database from its GUI, rebuilding the tables with the auto-generated DDL gleaned from an AnnotationConfiguration.
At the moment I do this by programatically setting hibernate.hbm2ddl.auto to create and then creating a new SessionFactory.
AnnotationConfiguration cfg = new AnnotationConfiguration();
if (nukeDB)
cfg.setProperty("hibernate.hbm2ddl.auto", "create");
for (Class<?> clas : HibernateMappedClasses) {
cfg.addAnnotatedClass(clas);
}
return cfg.buildSessionFactory();
but this requires creating a fresh AnnotationConfiguration from the one that Spring is building for the rest of the app.
Can I use my existing SessionFactory to recreate the database schema?
This isn't simple in raw Hibernate, but given that I'm using Spring, it turns out that the LocalSessionFactoryBean has methods dropDatabaseSchema and createDatabaseSchema that together do the trick.
Without Spring I think I'd copy the code in those methods!
We have a Spring/Hibernate app and would like to add a small amount of JDBC for reasons involving performance and development time. I can make this dao subclass HibernateDaoSupport and use the session's connection to perform my JDBC, but I'd rather use JdbcTemplate. JdbcTemplate, however is initialized using a java.sql.Datasource. How can I use my existing Hibernate SessionFactory to initialize it?
Aren't you required to provide a DataSource to the SessionFactory implementation? Why don't you wire that in to the JDBC Template?
Which SessionFactory implementation are you using? If you're using the Spring implementations, see AbstractSessionFactoryBean.html#getDataSource()
You can always use a hibernate session's doWork method - this gives you a java.sql.Connection. You can use this connection to construct a construct a SingleConnectionDataSource (note: the second argument should always be true as you don't want to close the underlying connection) and pass this datasource to your JDBCTemplate...
"extracting a datasource from our
hibernate configuration seems like a
lot of work for what I need"
I don't see why it would take that much work. It's just a matter of creating, cut-and-copying a couple of tags and properties.
For example:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
...
</bean>
"Which SessionFactory implementation
are you using? If you're using the
Spring implementations, see
AbstractSessionFactoryBean.html#getDataSource()"
Apparently, getDataSource() is only available for Spring 2.5. Here's the reference: Click here
Spring 2.0 doesn't have the getDataSource(). Here's the reference: Click here
Our session factory was created using
AnnotationSessionFactoryBean
initialized with hibernate properties
...
hibernateSessionFactory is a
SessionFactory. How would I get a
reference to the SessionFactoryBean?
I'm wondering why you used a SessionFactory instead of a LocalSessionFactoryBean which is a subclass of AnnotationSessionFactoryBean?
Isn't the line bean id="hibernateSessionFactory" references the SessionFactoryBean already?