How can I recreate my database with hibernate pojo files - java

I lost my projects' database from my pc. But I have my JSP project which includes hibernate. Whenever I run the project it says 'org.hibernate.exception.SQLGrammarException: Cannot open connection' because the database not exist in the server. Can I recreate my database with the help of the POJO files? I am using netbeans and MySQL server 5.1

Yes you can recreate your database using hibernate.
In our session factory you need to set the following property.
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
hibernate.hbm2ddl.auto Automatically validate or exports schema DDL to the database when the SessionFactory is created
There are a couple of caveats you need to understand:
This will only recreate objects which you had mapped. This process will not recreate any database object which you may have had but didn't have mapped.
Certain object names may not be named what they were previously. One classic example would be the names of your foreign-key constraints.
This will at least get you back up with a majority of what you lost at the very least.

Related

Hibernate creating Schemas on each application run?

I have built a web application using MVC pattern and Hibernate. I am trying to configure my hibernate to create schemas for my classes by using following property
<property name="hibernate.hbm2ddl.auto">create</property>
But, I found out that this drops the previous existing schema and re-creates schema on each application run. Is there anyway I configure my hibernate to create schemas only on my first application run and for any future application run just update the rows in existing database?
As YomanTaMero mentioned instead of :
<property name="hibernate.hbm2ddl.auto">create</property>
try this:
<property name="hibernate.hbm2ddl.auto">update</property>
Noticed "update" above?

Hibernate, load schema from file

In Hibernate, I can use hbm2dll tool to import data files after hibernate generates the schema from my model. This is fine, but I want to load the file with my database schema and make hibernate use that instead of generating one.
Let's say I have some database configured in my hibernate config
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>
Now before I run my test I want to load the db with some schema defined in my schema.sql file. And I don't want to use Spring, I know there is support for it there.
I know I could use hibernate.hbm2ddl to generate schema when SessionFactory is created but I'd rather want to load my manually defined schema. Something like <jdbc:embedded-database> from spring-jdbc.
Is there any support for that in Hibernate?
link1 and link2 might help you out.
Also you can set hibernate.hbm2ddl to none, and add your import.sql file in the classpath which will be executed at the server startup.

Dynamically disable hbm2ddl.auto?

I have a eclipse workspace with many projects, one project "shareddata" contains all my jpa entities, services, persistence.xml (using spring-data) and such. In my other projects i have included "shareddata" as dependency in my maven pom.xml .
When i start one of the other projects, jpa/hibernate validates and updates my database tables (hbm2ddl.auto = true). This works nicely.
But to test my entire project in need to start several projects that all include the "shareddata" project. So every single project validates and updates my database tables. This takes quite a bit of time.
Is it possible only to enable "hbm2ddl.auto" for one single project? Or is it possible to dynamically disable "hbm2ddl.auto" at application startup?
If that is possible than i could start up my jms server project and do database validation. Next i start up my other projects (tomcat and several server apps) and they won't do the database validation.
Saves me a lot of time :-)
I did such things via system properties. Unfortunately I do not know how do you initialize hibernate context. I personally did it via Spring that supports system properties using ${propName} syntax. If you can use this notation just use it in your configuration files and set appropriate property in the beginning of your unit test.
It took a little while to figure out, but jpa is configured in my applicationContext.xml (or variations like root-context.xml). LocalContainerEntityManagerFactoryBean does the initialization.
Lucky LocalContainerEntityManagerFactoryBean accepts parameters that seem to override the values set in persistence.xml . So i set hibernate.hbm2ddl.auto to none in persistence.xml and use the following xml to enable hibernate.hbm2ddl.auto for a specific project:
<!-- Add JPA support -->
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
Hope this may help someone with the same problem.

H2 database schema creation check

I have H2 database generated on the-fly using Hibernate & Spring for my test-cases.
I have few weird errors, and I would like to know exactly how the schema looks like in H2. how the tables defined, and how the columns.
How can I generate this report during run-time ?
If the schema is being deployed by Hibernate using hibernate.hbm2ddl.auto=true you could turn on trace logging for org.hibernate.tool.hbm2ddl. This would show you the DDL Hibernate is generating when it creates your schema.
You could run the SQL statement SCRIPT NODATA.
To see the SQL statements that are run against the database, append ;TRACE_LEVEL_FILE=2 to the database URL. This will write all SQL statements to the .trace.db file.
If you want to know what are the schemas getting generated on the fly. Simply add
<prop key="hibernate.show_sql">true</prop>
With this you'll be able to debug.

"Local transaction already has 1 non-XA Resource: cannot add more resources" error

After reading previous questions about this error, it seems like all of them conclude that you need to enable XA on all of the data sources. But:
What if I don't want a distributed
transaction? What would I do if I want to
start transactions on two different
databases at the same time, but
commit the transaction on one database
and roll back the transaction on
the other?
I'm wondering how my code
actually initiated a distributed
transaction. It looks to me like I'm
starting completely separate
transactions on each of the
databases.
Info about the application:
The application is an EJB running on a Sun Java Application Server 9.1
I use something like the following spring context to set up the hibernate session factories:
<bean id="dbADatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/dbA"/>
</bean>
<bean id="dbASessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dbADatasource" />
<property name="hibernateProperties">
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.default_schema=schemaA
</property>
<property name="mappingResources">
[mapping resources...]
</property>
</bean>
<bean id="dbBDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/dbB"/>
</bean>
<bean id="dbBSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dbBDatasource" />
<property name="hibernateProperties">
hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
hibernate.default_schema=schemaB
</property>
<property name="mappingResources">
[mapping resources...]
</property>
</bean>
Both of the JNDI resources are javax.sql.ConnectionPoolDatasoure's. They actually both point to the same connection pool, but we have two different JNDI resources because there's the possibility that the two, completely separate, groups of tables will move to different databases in the future.
Then in code, I do:
sessionA = dbASessionFactory.openSession();
sessionB = dbBSessionFactory.openSession();
sessionA.beginTransaction();
sessionB.beginTransaction();
The sessionB.beginTransaction() line produces the error in the title of this post - sometimes. I ran the app on two different sun application servers. On one runs it fine, the other throws the error. I don't see any difference in how the two servers are configured although they do connect to different, but equivalent databases.
So the question is
Why doesn't the above code start
completely independent transactions?
How can I force it to start
independent transactions rather than
a distributed transaction?
What configuration could cause the difference in
behavior between the two application
servers?
Thanks.
P.S. the stack trace is:
Local transaction already has 1 non-XA Resource: cannot add more resources.
at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.enlistResource(J2EETransactionManagerOpt.java:124)
at com.sun.enterprise.resource.ResourceManagerImpl.registerResource(ResourceManagerImpl.java:144)
at com.sun.enterprise.resource.ResourceManagerImpl.enlistResource(ResourceManagerImpl.java:102)
at com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:216)
at com.sun.enterprise.connectors.ConnectionManagerImpl.internalGetConnection(ConnectionManagerImpl.java:327)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:189)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:165)
at com.sun.enterprise.connectors.ConnectionManagerImpl.allocateConnection(ConnectionManagerImpl.java:158)
at com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:108)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:82)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1354)
at [application code ...]
1 Why doesn't the above code start completely independent transactions?
The app. server manages the transaction for you which can, if necessary, be a distributed transaction. It enlists all the participants automatically. When there's only one participant, you don't notice any difference with a plain JDBC transaction, but if there are more than one, a distributed transaction is really needed, hence the error.
2 How can I force it to start independent transactions rather than a
distributed transaction?
You can configure the datasource to be XA or Local. The transactional behavior of Spring/Hibernate can also be configured to use either regular JDBC transactions or delegate the management of transactions to the JTA distributed transaction manager.
I suggest you switch the datasource to non-XA and try to configure Spring/Hibernate to use the JDBC transactions. You should find the relevant information in the documentation, here what I suspect is the line to change:
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager" />
This should essentially means that you are not using the app. server distributed transaction manager.
3 What configuration could cause the difference in behavior between the
two application servers?
If you have really exactly the same app and configuration, this means that in one case only one participant is enlisted in the dist. transaction, while there are two in the 2nd case. One participant corresponds to one physical connection to a database usually. Could it be that in one case, you use two schema on two different databases, while in the 2nd case you use two schema on the same physical database? A more probable explanation would be that the datasource were configured differently on the two app. server.
PS: If you use JTA distributed transactions, you should use UserTransaction.{begin,commit,rollback} rather than their equivalent on the Session.
After reading previous questions about this error, it seems like all of them conclude that you need to enable XA on all of the data sources.
No, not all, all except one (as the exception is saying) if your application server supports Logging Last Resource (LLR) optimization (which allows to enlist one non-XA resource in a global transaction).
Why doesn't the above code start completely independent transactions?
Because you aren't. When using beginTransaction() behind EJB Session Beans, Hibernate will join the JTA transaction (refer to the documentation for full details). So the first call just works but the second call means enlisting another transactional resource in the current transaction. And since none of your resources are XA, you get an exception.
How can I force it to start independent transactions rather than a distributed transaction?
See #ewernli answer.
What configuration could cause the difference in behavior between the two application servers?
No idea. Maybe one of them is using at least one XA datasource.

Categories