I am using #Transactional annotation to test inserting some data into one of the tables through a Spring application. My test succeeds, but I do not see any data being inserted into the table.
Here are the relevant code snippets:
MyTest:
#TransactionConfiguration(transactionManager="MyTxManager")
#Transactional
public class MyTest {
#Autowired
private DataProvider provider;
#Test
#Transactional
void testInsert() {
Order purchaseOrder = new Order("ID1", "LER", "VDR1", 0, );
provider.addRow(purchaseOrder);
}
}
DataProvider:
public class DataProvider extends DatabaseProvider {
// some stuff...
#Transactional
public void insertRow(Order purchaseOrder) {
/*
* SessionFactory is got through autowiring
* and is working perfectly fine.
*/
Session session = sessionFactory.getCurrentSession();
// This should save the row into the table - which it doesn't :(
session.save(purchaseOrder);
}
}
information-providers.xml
<bean id="DataProvider" class="com.util.DataProvider">
<property name="sessionFactory" ref="MySessionFactory" />
</bean>
hibernate.xml containing the configuration of session factory
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
parent="AbstractSessionFactory" depends-on="EnvironmentHelper">
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="hibernate.connection.provider_class">com.hibernate.ConnectionPool</prop>
<prop key="hibernate.connection.driver_class">${driverClassName}</prop>
<prop key="hibernate.connection.url">${databaseURL}</prop>
<prop key="hibernate.connection.username">${databaseUsername}</prop>
<prop key="hibernate.connection.password">${databasePassword}</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.default_schema">${databaseDefaultSchema}</prop>
</props>
</property>
</bean>
<!-- Use Spring transactions for Hibernate -->
<tx:annotation-driven transaction-manager="MyTxManager" mode='proxy' proxy-target-class='true'/>
<bean id="MyTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="MySessionFactory" />
</bean>
</beans>
I think the problem in rolling back the transactions. See here defaultRollback method.
Try like this:
#TransactionConfiguration(transactionManager="MyTxManager", defaultRollback=false)
Your problem is that MyProvider myProviderInstance = new MyProvider(); the myProviderInstance isn't maintained by Spring container, you just new it, so the Spring can't do anything about it, definitely the transaction doesn't work. You should config the bean in Spring applicationcontext.xml and load it with ApplicationtContext, you can find dozens of sample after google it. And since you use Mysql you should make sure that you use innerDB mode or the transaction isn't supported by mysql.
add the line <tx:annotation-driven/> to your spring configuration
Related
Say we input username: hello The entity below save the user info in User regU
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int user_id;
#Column(name = "username")
private String username;
The database already have 3 users with (auto_increment) id 1,2 and 3
Then we run the JPA save method:
URepo.save(regU)
Would the user normally get saved with id 4?
I tried test to this in my code, but when I run the save() method, literally nothing happens, hibernate doesn't show me the query it ran, no exception thrown, no changes in database.
My other queries print to console, but not save().
My JPA has these properties:
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="format_sql">true</prop>
<prop key="use_sql_comments">true</prop>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
Edit 1:
My current code gives the new entity the id of 0, how would spring-data save an id of 0, and is it normal for the new entity to have id of 0 rather than the auto_increment value?
i'm kinda new on web dev, i'm a trainee on a company since last year and i have the following problem:
I'm making a web app with JSF2.3 and Hibernate 5.4.2.Final and c3p0 5.4.2.Final. The thing is everytime i run and go for the login page, i need to check if there is an admin user already registered - i make a count on employee's table based on employee's code - and if there isn't any administrator, then i get a list of country states and render a form register menu.
So, i get the session from the sessionfactory.opensession() in mine HibernateUtil.class, do the count and clear/close the session like the snipet:
public Long retornaLong(String query) throws Exception{
Session session = new HibernateUtil().getSession();
try {
return (Long) session.createQuery(query).getSingleResult();
}finally {
session.clear();
session.close();
}
}
then i get the country states list from
#SuppressWarnings("unchecked")
public List<T> retornaList(String query) throws Exception{
Session session = new HibernateUtil().getSession();
try {
return (List<T>) session.createQuery(query).getResultList();
}finally {
session.clear();
session.close();
}
}
but if i keep refreshing the page (#viewscoped), like 15+ times, eventually i'll get too many connection exception, this doesn't happen if i use one session for both queries. I think there's no enough time for the session to close, causing a connection leak. I want to use one session for each query, can someone help me. Thanks a lot.
My hibernate.cfg.xml
<hibernate-configuration>
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory>
<!-- properties -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/vetsnpets?useTimezone=true&serverTimezone=UTC</property>
<property name="hibernate.connection.username">vetsNpets</property>
<property name="hibernate.connection.password">123</property>
<property name="hiberante.show_sql">false</property>
<property name="hiberante.format_sql">false</property>
<property name="hbm2ddl.auto">validate</property>
<property name="current_session_context_class">thread</property>
<!-- C3P0 -->
<property name="hibernate.c3p0.initialPoolSize">3</property>
<property name="hibernate.c3p0.minPoolSize">3</property>
<property name="hibernate.c3p0.maxPoolSize">20</property>
<property name="hibernate.c3p0.maxStatements">100</property>
<property name="hibernate.c3p0.maxStatementsPerConnection">5</property>
<property name="hibernate.c3p0.maxIdleTime">2700</property>
<property name="hibernate.c3p0.maxIdleTimeExcessConnections">600</property>
<property name="hibernate.c3p0.acquireIncrement">1</property>
This is very strange in my RESTful WS development. I am using Tomcat 7 with Jersey 1.8, Spring 2.5 and MySQL database.
I defined two data sources like this:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
<property name="jndiName" value="jdbc/MAINDB" />
<property name="resourceRef" value="true" />
</bean>
<bean id="orderDataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
<property name="jndiName" value="jdbc/ORDERS" />
<property name="resourceRef" value="true" />
</bean>
and inject one data source into the servlet context like this:
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
<property name="attributes">
<map>
<entry key="orderData">
<ref bean="orderDataSource" />
</entry>
</map>
</property>
</bean>
and this code:
orderDataSource = (DataSource) sc.getServletContext().getAttribute("orderData");
Order ord = new Order();
Statement stmt = null;
try {
stmt = orderDataSource.getConnection().createStatement();
} catch (SQLException ex) {
Logger.getLogger(OrdersResource.class.getName()).log(Level.SEVERE, null, ex);
}
gets executed 6 or 7 times flawlessly and from the 8th request, it gets stall at createStatement() line and never return or throw any exception!
However, all other resources API from MAINDB still works very well.
Anyone knows what's happening?
Why are you bothering with such code yourself? If you are using Spring already, use the JdbcTemplate instead. It can be initialized with your DataSource and will manage all that for you.
You are requiring a connection from the pool but you never closes it (same for the statement actually). Using JdbcTemplate prevents you from having those issues in the first place.
Something like
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute(...)
See the javadoc for more details.
I have a problem when I insert data in my MySQL database with Spring Data Jpa Module.
The problem is the following:
When I startup my Springapplication I create the database and initialize the data with SpringdataJPA and I see the data inserted in the table. Afterwards i wanna insert some data related to inserted data and only 1 of the 3 records inserted before were found. When i restard the server and i dont recreate the data and search for it with the same method every single record is found. I search for 2 weeks for a solution but didnt find anything. I hope you can help me.
NEWS
I think only in words is hard to understand, so I insert the code behind. jpa.xml with all spring jpa configuration. The 2 entities and the initmethods. hopefully you can find my error.
jpa.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder location="classpath:properties/database/database.properties" />
<!-- Declare a datasource that has pooling capabilities-->
<!-- BoneCP configuration -->
<bean id="SoopDataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close" >
<property name="driverClass" value="${database.driver}" />
<property name="jdbcUrl" value="${database.url}" />
<property name="username" value="${database.user}"/>
<property name="password" value="${database.password}"/>
<property name="idleConnectionTestPeriod" value="60"/>
<property name="idleMaxAge" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="5"/>
<property name="partitionCount" value="2"/>
<property name="acquireIncrement" value="5"/>
<!-- <property name="statementsCacheSize" value="100"/> -->
<!-- <property name="releaseHelperThreads" value="2"/> -->
</bean>
<!-- Declare a JPA entityManagerFactory-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="persistenceUnitName" value="SoopDbProvider" />
<property name="dataSource" ref="SoopDataSource"/>
<property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.soopproject.main.db</value>
</list>
</property>
</bean>
<!-- Db initialization bean -->
<bean id="databaseinit" class="com.soopproject.main.db.init.DatabaseInitialization" init-method="init"/>
<!-- Declare a transaction manager-->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Entities:
BaseEntityWithPrimary
#MappedSuperclass
#Data
#EqualsAndHashCode(callSuper = false)
public class SoopBaseEntityWithPrimary implements
Serializable {
#Id
#GeneratedValue
private long id;
}
Language:
#Entity
#Data
#EqualsAndHashCode(callSuper = true)
public class Language extends BaseEntityWithPrimary {
#Column(nullable = false, unique = true)
private String shortname;
#Column(nullable = false)
private String longname;
#ManyToMany(cascade = CascadeType.ALL)
private List<TranslationsShort> languageTranslationsShorts;
}
InitMethods
#Autowired
private UserRepository userrep;
#Autowired
private LanguageRepository langrep;
#Autowired
private ErrorCodesRepository errorrep;
private void initLanguage() {
User systemuser = null;
try {
systemuser = userrep.findUserByUsername("system");
} catch (Exception ex) {
DatabaseException exception = new DatabaseReadException(ex);
exception.writeLog();
}
List<Language> languages = new LinkedList<>();
Language deutsch = new Language();
deutsch.setCreateUser(systemuser);
deutsch.setShortname("DE");
deutsch.setLongname("Deutsch");
Language english = new Language();
english.setCreateUser(systemuser);
english.setShortname("EN");
english.setLongname("English");
Language italiano = new Language();
italiano.setCreateUser(systemuser);
italiano.setShortname("IT");
italiano.setLongname("Italiano");
languages.add(deutsch);
languages.add(italiano);
languages.add(english);
for (Language lang : languages) {
Language l_help = null;
try {
l_help = langrep.findLanguageByShortname(lang.getShortname());
} catch (Exception ex) {
DatabaseException exception = new DatabaseReadException(ex);
exception.writeLog();
}
if (l_help == null)
try {
langrep.saveAndFlush(lang);
} catch (Exception e) {
DatabaseException exception = new DatabaseWriteException(e);
exception.writeLog();
}
}
}
private void initErrorCodes() {
User systemuser = null;
Language de = null;
Language it = null;
Language en = null;
try {
systemuser = userrep.findUserByUsername("system");
} catch (Exception ex) {
DatabaseException exception = new DatabaseReadException(ex);
exception.writeLog();
}
try {
de = langrep.findLanguageByShortname("DE");
} catch (Exception ex) {
DatabaseException exception = new DatabaseReadException(ex);
exception.writeLog();
}
try {
it = langrep.findLanguageByShortname("IT");
} catch (Exception ex) {
DatabaseException exception = new DatabaseReadException(ex);
exception.writeLog();
}
try {
en = langrep.findLanguageByShortname("EN");
} catch (Exception ex) {
DatabaseException exception = new DatabaseReadException(ex);
exception.writeLog();
}
The problem is that after startup the springapplication and set <prop key="hibernate.hbm2ddl.auto">create</prop> in the method initErrorCodes only the line with it = langrep.findLanguageByShortname("IT"); finds the data in database. The other 2 calls return null (de = langrep.findLanguageByShortname("DE"); and en = langrep.findLanguageByShortname("EN");). Then i stop the application and look to the database and all data is inserted in the table Language. When i restart the server with <prop key="hibernate.hbm2ddl.auto">none</prop> then all 3 method calls return the data???!?!?! I dont get it. So for sure it's not a problem of the method call. But I cant find the error.
What do you mean by 1 of 3 were found? Are you querying the data, or accessing a relationship?
It sounds like some sort of caching is occurring. Some JPA providers enable caching by default, check you cache settings, and ensure you are maintaining bidirectional relationships correctly.
https://en.wikibooks.org/wiki/Java_Persistence/Caching
https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Object_corruption.2C_one_side_of_the_relationship_is_not_updated_after_updating_the_other_side
I'm starting to develop a test application with Spring MVC and Hibernate, and I have a question about the database configuration.
I know I am able to define the datasource through the application-context.xml, like
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
But I wanted not to use XML at all, so I created a configuration class in which I wanted to load a DataSource object, with a method similar to this:
#Bean
public DataSource dataSource() {
...
}
My question is: how can I get a DataSource instance that points to my MySQL schema? If there are several options, which is the best in your opinion?
I want to use a MySQL database, not an embedded one
Thanks
As I was working with Spring MVC, I solved it in the following way:
#Bean
public DriverManagerDataSource getMySQLDriverManagerDatasource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setPassword("password");
dataSource.setUrl("jdbc:mysql://localhost:3306/mytestdb");
dataSource.setUsername("root");
return dataSource;
}