I have a trouble when running my web application that tries to get all the information from the table snowboard and put it in a list which I will then print out in the xHtml. But I get this exception down below.
org.hibernate.TransactionException: nested transactions not supported
The thing is that I have no clue why this exception happens so would appreciate some explanation. Also if you find any trouble in the code that would be fantastic.
This is the exception that I get.
HibernateUtil
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory from standard (hibernate.cfg.xml)
// config file.
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Log the exception.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
SnowHelper, HelperClass
public class SnowHelper {
Session session = null;
public SnowHelper() {
this.session = HibernateUtil.getSessionFactory().getCurrentSession();
}
public List getSnowboards() {
List<Snowboard> snowboardList = null;
try {
Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Snowboard");
snowboardList = (List<Snowboard>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return snowboardList;
}
}
HibernateCfg
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://cpsrv01.misshosting.com:3306/etvffqgz_snowshop</property>
<property name="hibernate.connection.username">etvffqgz_user</property>
<property name="hibernate.connection.password">759486456</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</property>
<mapping resource="Hibernate/Account.hbm.xml"/>
<mapping resource="Hibernate/Snowboard.hbm.xml"/>
</session-factory>
</hibernate-configuration>
SnowboardBean, ManagedBean class
#Named(value = "snowboardBean")
#Dependent
public class SnowboardBean {
private List<Snowboard> snowList;
private SnowHelper snow;
/**
* Creates a new instance of SnowboardBean
*/
public SnowboardBean() {
snowList = new ArrayList<>();
snow = new SnowHelper();
snowList = snow.getSnowboards();
}
/**
* #return the snowList
*/
public List<Snowboard> getSnowList() {
return snowList;
}
}
In this bit here.. commit your transaction
Transaction tx = session.beginTransaction();
Query q = session.createQuery("from Snowboard");
snowboardList = (List<Snowboard>) q.list();
tx.commit();
Otherwise you simply open a new transaction without closing it every time you invoke this method.. eventually one of them is opened while some other is not commited yet.
If you were using 'container managed transactions' (provided by Spring of EJB's) you would not have to worry about explicitly committing your transactions. Here you are using 'extended transaction management' and you have to take care of that yourself.
Related
I’m learning Java and Hibernate. Right now, I’m having trouble understanding how to use a custom physical naming strategy: While the PhysicalNamingStrategy object is indeed instantiated, the toPhysicalTableName or toPhysicalColumnName methods are never called – not that I can see with a debugger, at least.
Versions: Java 1.8, Hibernate 5.2.10.Final, on macOS 10.12.
Here’s a minimal project:
#Entity
public class Cake {
#Id
private long id;
private String name;
private String FLAVOUR;
private int sErViNg;
public Cake(String name, String flavour, int serving) {
this.name = name;
this.FLAVOUR = flavour;
this.sErViNg = serving;
}
// getters and setters
public class Main {
public static void main (String[] args) {
Transaction tx = null;
try (
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
) {
tx = session.beginTransaction();
Cake cake = new Cake("Molten Chocolate Cake", "chocolate", 1);
session.save(cake);
tx.commit();
}
catch (Exception e) {
e.printStackTrace();
if ( tx != null ) {
tx.rollback();
}
}
}
}
public class AllCapsPhysicalNamingStrategy
extends PhysicalNamingStrategyStandardImpl implements Serializable {
public static final AllCapsPhysicalNamingStrategy INSTANCE
= new AllCapsPhysicalNamingStrategy();
#Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
return new Identifier(name.getText().toUpperCase(), name.isQuoted());
}
#Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
return new Identifier(name.getText().toUpperCase(), name.isQuoted());
}
}
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/cake</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.hbm2ddl.auto">create</property>
<property name="hibernate.physical_naming_strategy">com.example.AllCapsPhysicalNamingStrategy</property>
<mapping class="com.example.Cake"/>
</session-factory>
</hibernate-configuration>
Here’s the table I get:
[cake]> SELECT * FROM cake;
+----+-----------+-----------------------+---------+
| id | FLAVOUR | name | sErViNg |
+----+-----------+-----------------------+---------+
| 0 | chocolate | Molten Chocolate Cake | 1 |
+----+-----------+-----------------------+---------+
I would expect:
+----+-----------+-----------------------+---------+
| ID | FLAVOUR | NAME | SERVING |
+----+-----------+-----------------------+---------+
| 0 | chocolate | Molten Chocolate Cake | 1 |
+----+-----------+-----------------------+---------+
What am I doing wrong here?
This isn't very well documented but unfortunately it seems Hibernate doesn't support that particular property being set in hibernate.cfg.xml. To quote from a very old Hibernate forum post:
You can set the properties given Environment.java class only in
hibernate.properties or hibernate.cfg.xml. Rest of the properties like
NamingStrategy has to be configured with Configuration class.
So would recommend removing the property and instead setting this in code on the Configuration instance, as proposed by Shiv Raghuwanshi.
You can set in configuration also.
public class Main {
public static void main (String[] args) {
Transaction tx = null;
try (
Configuration configuration =new Configuration();
configuration.setPhysicalNamingStrategy(new AllCapsPhysicalNamingStrategy());
SessionFactory sessionFactory = configuration.configure().buildSessionFactory();
Session session = sessionFactory.openSession();
) {
tx = session.beginTransaction();
Cake cake = new Cake("Molten Chocolate Cake", "chocolate", 1);
session.save(cake);
tx.commit();
}
catch (Exception e) {
e.printStackTrace();
if ( tx != null ) {
tx.rollback();
}
}
}
}
There is nothing wrong with the your configuration. It is just that bootstrapping hibernate using Configuration object requires you to set some of the config property on configuration object itself. These configuration specified via properties will get ignored.
Also, bootstrapping hibernate using Configuration object is considered as "legacy" way (as per official hibernate docs) and newer way is recommended of bootstrapping the hibernate as shown below.
public static void main(String[] args) {
Transaction tx = null;
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure() // using "hibernate.cfg.xml"
.build();
Metadata metadata = new MetadataSources(standardRegistry).buildMetadata();
try (
SessionFactory sessionFactory = metadata.getSessionFactoryBuilder().build();
Session session = sessionFactory.openSession();) {
tx = session.beginTransaction();
Cake cake = new Cake("Molten Chocolate Cake", "chocolate", 1);
session.save(cake);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
This will pick the Physical naming strategy specified as hibernate property in hibernate.cfg.xml file.
I am using hibernate in my project : config
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#oracle...</property>
<property name="hibernate.connection.username">name</property>
<property name="hibernate.connection.password">passwd</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.enable_lazy_load_no_trans">true</property>
<mapping resource="db/Sanitka.hbm.xml"/>
<mapping resource="db/Sanitari.hbm.xml"/>
<mapping resource="db/Nemocnica.hbm.xml"/>
</session-factory>
</hibernate-configuration>
and my helper file looks like this
public class helper {
private static Session session = NewHibernateUtil.getSessionFactory().getCurrentSession();
public static List<Sanitka> getNemocnicas() {
List<Nemocnica> filmList = null;
org.hibernate.Transaction tx = null;
try {
tx = session.beginTransaction();
Query q = session.createQuery ("from Nemocnica");
filmList = (List<Nemocnica>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return filmList;
}
public static List<Nemocnica> getSanitkas() {
List<Nemocnica> filmList = null;
org.hibernate.Transaction tx = null;
try {
tx = session.beginTransaction();
Query q = session.createQuery ("from Sanitka");
filmList = (List<Nemocnica>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return filmList;
}
}
I am building restful api , the
/nemocnica
route invokes getNemocnicas()
and /sanitkas route invokes getSanitkas()
What is problem is that when i go to /nemocnica getNemocnicas() is invoked and return query from database , however when after that i want to go to /sanitkas
it throws
org.hibernate.TransactionException: nested transactions not supported
error. I read that it is bcs i am not closing session from previous transaction. But when i added
if( tx != null)
tx.commit()
before return statement in those methods , it threw this error :
org.hibernate.SessionException: Session is closed!
What is the optimal way to close transaction then?
Thanks for help!
I saw nearly all questions and answers for this on stackoverflow, but all answers are the same. That you should use something like this Query query = session.createQuery("from theme").list();
but .list() is depricated and I can´t use it anymore.
So the first Question is, what should I use instead of .list()and why I get this exeption java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: theme is not mapped [from theme]
Query Method
public ObservableList<String> getThemes(){
ObservableList<String> obsList = FXCollections.observableArrayList();
SessionFactory factory = new Configuration()
.configure("hibernate.cfg.xml")
.buildSessionFactory();
Session session = factory.getCurrentSession();
try {
session.beginTransaction();
Query query = session.createQuery("from theme"); // why not mapped
//cant use .list()?
session.getTransaction().commit();
System.out.println("query " + query);
} catch (Exception e) {
e.printStackTrace();
}finally{
session.close();
}
return obsList; // nothing at the moment
hibernate.cfg.xml
<!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="connection.driver_class">org.sqlite.JDBC</property>
<!-- I know sqlite with an mysql dialect isnt the best, in the future it
will be mySql--> <property
name="connection.url">jdbc:sqlite:C:\\DokiDB\\database.db</property>
<property name="connection.username">progdm</property>
<property name="connection.password">release</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.pool_size">1</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>
mapped class
#Entity
#Table(name="theme")
public class mapTheme {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="theme_id")
private int theme_id;
#Column(name="theme_name")
private String theme_name;
public int getTheme_id() {
return theme_id;
}
public void setTheme_id(int theme_id) {
this.theme_id = theme_id;
}
public String getTheme_name() {
return theme_name;
}
public void setTheme_name(String theme_name) {
this.theme_name = theme_name;
}
public mapTheme(String theme_name) {
super();
this.theme_name = theme_name;
}
public mapTheme(){
}
}
what can I do?
The table name used in the query is not the name of the table in database, it should be the name of the entity class.
In this case you must use
Query query = session.createQuery("from mapTheme");
instead of :
Query query = session.createQuery("from theme")
I'm using hibernate to add my objects into the database.
When I call sessionCacti.save(Object object) it stores the object to database while the object shouldn't not be stored because I didn't commit the changes and I use a non auto-commit mode.
Here is the file of the configuration of hibernate
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="hibernate.current_session_context_class">thread</property>
<!-- pcac is the database name -->
<property name="hibernate.connection.url">
jdbc:mysql://uaeipvm1:3307/pcac?zeroDateTimeBehavior=convertToNull
</property>
<property name="hibernate.connection.username">
myadmin
</property>
<property name="hibernate.connection.password">
dbaft
</property>
<!-- 1: READ UNCOMMITTED 2: READ COMMITTED 4: REPEATABLE READ 8: SERIALIZABLE -->
<property name="hibernate.connection.isolation">2</property>
<!-- List of XML mapping files -->
<mapping resource="Host.hbm.xml" />
<mapping resource="HostGraph.hbm.xml" />
<mapping resource="HostTemplate.hbm.xml" />
<mapping resource="HostTemplateGraph.hbm.xml" />
<mapping resource="Settings.hbm.xml" />
</session-factory>
</hibernate-configuration>
And this is my program :
public class SynchroCacti {
public static Map<String,Host> hosts = new HashMap<String, Host>();
private static SessionFactory factoryDerbi,factoryCacti;
private static Transaction tx=null;
private static Session sessionDerbi,sessionCacti;
public static List<Equipment> derbiEquipments;
private static List<HostTemplate> hostTemplates;
private static List<Settings> settings;
private static int nbNewHosts = 0;
private static int initialNbCactiHost,initialNbDerbiEqpts;
public static void initializeData ()
{
try{
factoryDerbi = new Configuration().configure("/hibernate_derbi.cfg.xml").buildSessionFactory();
factoryCacti = new Configuration().configure("/hibernate_cacti.cfg.xml").buildSessionFactory();
sessionDerbi = factoryDerbi.openSession();
sessionCacti = factoryCacti.openSession();
tx = sessionCacti.beginTransaction();
}catch (Throwable ex) {
logErrorsInProgram.error("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
//Store tables of the database in these lists
derbiEquipments = sessionDerbi.createCriteria(Equipment.class).list();
List<Host> cactiHosts = sessionCacti.createCriteria(Host.class).list();
hostTemplates = sessionCacti.createCriteria(HostTemplate.class).list();
settings = sessionCacti.createCriteria(Settings.class).list();
//Initialize the hash map of hosts
Iterator<Host> it = cactiHosts.iterator();
while (it.hasNext())
{
Host actual = it.next();
hosts.put(actual.getDescription(), actual);
}
//Initialize values of initialNbCactiHost and initialNbDerbiEqpts from sizes of lists
initialNbCactiHost = hosts.size();
initialNbDerbiEqpts = derbiEquipments.size();
}
public static void addHostToDatabase (Host host)
{
nbNewHosts++;
try{
sessionCacti.save(host);
}catch (ConstraintViolationException e) {
if (tx!=null) tx.rollback();
}finally { //We don't close session
}
}
public static void main(String[] args) throws HibernateException, SQLException, ParseException {
initializeData();
Host host = createHost(derbiEquipments.get(0));
addHostToDatabase(host);
}
}
I don't want to save data until I execute tx.commit();
Thanks.
I am getting this below exception when I am trying to execute a Stored procedure using HIbernate from DaoImpl Class.
I am not sure of what is wrong ..I tried all the ways to fix it but did not resolve the issue.
Could anyone please help me ,figure out whats wrong with the code or the mapping file.
The more I am trying to fix ,something the more exceptions I am getting.. I am connectuing to Oracle 9i DB.
I am struggling on this from really 2 weeks ending up no where.. can anyone please help me fix this issue.
Mapping file:
<hibernate-mapping>
<sql-query name="proc_drsrr_sel_ValDDSummaryBal">
<!--CALL proc_drsrr_sel_ValDDSummaryBal(:param1)]]>-->
{ call DEFAULT_SCHEMA.proc_name(?,:param1) }
Main-Class:
public static void main(String[] args) {
String procName = "proc_name";// args[0];
String params = "param1:500089" ;
DAO Implementation:
#SuppressWarnings("unchecked")
public void callProc(String procName, Map paramMap) throws SQLException {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSessionFactory().getCurrentSession();
tx = session.beginTransaction();
String dbURL = session.connection().getMetaData().getURL().toString();
System.out.println("Conenction DB URL "+ dbURL );
tx.setTimeout(5);
String[] keys = new String[paramMap.size()];
keys = (String[]) paramMap.keySet().toArray(keys);
Query query = session.getNamedQuery(procName)
.setParameter("param1", "5501010");
}
List result = query.list();
System.out.println(query.getQueryString());
for (int i = 0; i < result.size(); i++) {
// logging the information.
log.info(i);
}
tx.commit();
} catch (RuntimeException exception) {
exception.printStackTrace();
try {
tx.rollback();
} catch (RuntimeException rbe) {
log.error("Couldn’t roll back transaction", rbe);
rbe.printStackTrace();
}
throw exception;
} finally{
if(session !=null){
session.flush();
session.close();
}
cfg.xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">jdbc:oracle:thin:#ldap://hdsoid.ute.ovi.com:3060/UT1DEV,cn=OracleContext,dc=ute,dc=ovi,dc=com</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.username">nameapp</property>
<property name="connection.password">nameapp</property>
<property name="connection.pool_size">1</property>
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<!-- <property name="connection.release_mode">after_statement</property> -->
<property name="default_schema">DEFAULT_SCHEMA</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<!-- mapping files -->
<mapping resource="com/ovi/domain/hibernate.hbm.xml" />
</session-factory>
</hibernate-configuration>
You are missing to set the ? parameter which is a so called positional parameter. In contrast to named parameters like :foo
When you have some SQL you must also ensure not to have any Question Marks inside comments! That's what I just ran into. Same holds for : in comments, especially if they are followed by a space.