I'm trying to learn how to use the @Transactional annotation in Spring (I'm not using Spring Boot). But when I swich from my - working - method using begin() and commit() ton the one with @Transactional, my entities aren't persisted. Can you help me understand what I'm doing wrong?
Without transactional/working method:
public <S extends Message> S save(S entity) {
EntityManager em = pu.getEntityManager();
try {
logger.debug("Trying to save " + ((Message) entity).toString());
em.getTransaction().begin();
em.persist(entity);
em.getTransaction().commit();
logger.debug("MessageRepository.save() - after .commit()");
}
catch (PersistenceException e) {
logger.error("Entity already exists");
e.printStackTrace();
}
finally {
System.out.println();
em.close();
}
return entity;
}
With @Transactional/not working:
@Transactional
@Override
public <S extends Message> S save(S entity) {
EntityManager em = pu.getEntityManager();
em.persist(entity);
return entity;
}
And here is my PersustanceUtil (pu) class:
package com.cypherf.repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.annotation.PreDestroy;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
@Service
public class PersistenceUtil {
private static EntityManagerFactory emf = null;
@Bean
public PlatformTransactionManager txManager() {
return new JpaTransactionManager(getEntityManagerFactory());
}
/**
* Creates entity manager factory as singleton instance and returns it
*
* @return the EntityManagerFactory
*/
public EntityManagerFactory getEntityManagerFactory() {
if (emf == null) {
synchronized (EntityManagerFactory.class) {
if (emf == null) {
final StandardServiceRegistry sr = new StandardServiceRegistryBuilder()
.configure() // Configures setting from hibernate.cfg.xml
.build();
try {
emf = new MetadataSources(sr).buildMetadata().buildSessionFactory();
}
catch (Exception e) {
StandardServiceRegistryBuilder.destroy(sr);
throw e;
}
}
}
}
return emf;
}
/**
* Closes the entity manager factory
*/
@PreDestroy
public static void closeEntityManagerFactory() {
System.out.println("PersistenceUtil.closeEntityManagerFactory()");
if (emf != null) {
System.out.println("Closing emf");
emf.close();
}
}
/**
* Returns a new EntityManager instance
*
* @return the new EntityManager instance
*/
public EntityManager getEntityManager() {
return getEntityManagerFactory().createEntityManager();
}
}
Main class:
package com.cypherf;
import com.cypherf.model.Message;
import com.cypherf.repository.MessageRepository;
import com.cypherf.service.MessageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan
@EnableTransactionManagement
public class TestSpringApplication {
@Autowired
private ApplicationContext context;
@Autowired
private CrudRepository<Message, Long> messageRepository;
@Autowired
private MessageService messageService;
final static Logger logger = LoggerFactory.getLogger(TestSpringApplication.class);
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(TestSpringApplication.class);
TestSpringApplication app = ctx.getBean(TestSpringApplication.class);
logger.info("Running app...");
app.run(args);
//TestSpringApplication app = context.getBean(TestSpringApplication.class);
//TestSpringApplication app = new TestSpringApplication();
//app.run(args);
}
public void run(String... args) {
messageRepository.save(new Message("Message one"));
messageRepository.save(new Message("Message two"));
messageService.printAllMessages();
messageRepository.save(new Message("Message two"));
messageService.printAllMessages();
// System.out.println("BEANS:");
// List<String> beans = Arrays.asList(context.getBeanDefinitionNames());
// beans.forEach(bean -> System.out.println(bean));
}
}
Here is the output:
[...]
2419 [main] DEBUG org.hibernate.event.internal.EntityCopyObserverFactoryInitiator - Configured EntityCopyObserver strategy: disallow
2518 [main] DEBUG org.hibernate.boot.internal.ClassLoaderAccessImpl - Not known whether passed class name [com.cypherf.model.Message] is safe
2518 [main] DEBUG org.hibernate.boot.internal.ClassLoaderAccessImpl - No temp ClassLoader provided; using live ClassLoader for loading potentially unsafe class : com.cypherf.model.Message
2790 [main] DEBUG org.hibernate.bytecode.internal.bytebuddy.BytecodeProviderImpl - HHH000513: Unable to create the ReflectionOptimizer for [com.cypherf.model.Message]: private accessor [text]
2853 [main] DEBUG org.hibernate.orm.model.mapping.creation - Starting post-init callbacks
2853 [main] DEBUG org.hibernate.orm.model.mapping.creation - Starting PostInitCallbackEntry : Entity(com.cypherf.model.Message) `staticFetchableList` generator
2853 [main] DEBUG org.hibernate.orm.model.mapping.creation - Starting PostInitCallbackEntry : Entity(com.cypherf.model.Message) `sqmMultiTableInsertStrategy` interpretation
2946 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Static SQL for entity: com.cypherf.model.Message
2946 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Version select: select id from Message where id=?
2946 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Insert (0): insert into Message (text,id) values (?,?)
2946 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Update (0): update Message set text=? where id=?
2946 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Delete (0): delete from Message where id=?
2962 [main] DEBUG org.hibernate.orm.sql.ast.create - Created new SQL alias : m1_0
2962 [main] DEBUG org.hibernate.orm.sql.ast.create - Registration of TableGroup [StandardTableGroup(com.cypherf.model.Message)] with identifierForTableGroup [com.cypherf.model.Message] for NavigablePath [com.cypherf.model.Message]
2993 [main] DEBUG org.hibernate.orm.results.graph.AST - DomainResult Graph:
\-EntityResultImpl [com.cypherf.model.Message]
| \-BasicFetch [com.cypherf.model.Message.text]
2993 [main] DEBUG org.hibernate.orm.sql.ast.tree - SQL AST Tree:
SelectStatement {
FromClause {
StandardTableGroup (m1 : com.cypherf.model.Message) {
primaryTableReference : Message as m1_0
}
}
}
3040 [main] DEBUG org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator - No JtaPlatform was specified, checking resolver
3040 [main] DEBUG org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator - No JtaPlatformResolver was specified, using default [org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver]
3056 [main] DEBUG org.hibernate.engine.transaction.jta.platform.internal.StandardJtaPlatformResolver - Could not resolve JtaPlatform, using default [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
3056 [main] INFO org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator - HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
3056 [main] DEBUG org.hibernate.type.spi.TypeConfiguration$Scope - Scoping TypeConfiguration [org.hibernate.type.spi.TypeConfiguration@4d27d9d] to SessionFactoryImplementor [org.hibernate.internal.SessionFactoryImpl@3a209918]
3056 [main] DEBUG org.hibernate.query.named.NamedObjectRepository - Checking 0 named HQL queries
3056 [main] DEBUG org.hibernate.query.named.NamedObjectRepository - Checking 0 named SQL queries
3071 [main] DEBUG org.hibernate.SQL -
drop table if exists Message cascade
Hibernate:
drop table if exists Message cascade
3087 [main] INFO org.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@5170bc02] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
3088 [main] DEBUG org.hibernate.SQL -
drop sequence if exists Message_SEQ
Hibernate:
drop sequence if exists Message_SEQ
3088 [main] DEBUG org.hibernate.SQL -
create sequence Message_SEQ start with 1 increment by 50
Hibernate:
create sequence Message_SEQ start with 1 increment by 50
3088 [main] INFO org.hibernate.orm.connections.access - HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@4601047] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
3103 [main] DEBUG org.hibernate.SQL -
create table Message (
id bigint not null,
text varchar(255) unique,
primary key (id)
)
Hibernate:
create table Message (
id bigint not null,
text varchar(255) unique,
primary key (id)
)
3119 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Initializing SessionFactoryRegistry : org.hibernate.internal.SessionFactoryRegistry@40dd552c
3119 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Registering SessionFactory: 0c3c67af-87cc-4b0a-bfd9-a5e6498e66fc (<unnamed>)
3119 [main] DEBUG org.hibernate.internal.SessionFactoryRegistry - Not binding SessionFactory to JNDI, no JNDI name configured
3119 [main] DEBUG org.hibernate.internal.SessionFactoryImpl - Instantiated SessionFactory
3176 [main] DEBUG org.hibernate.stat.internal.StatisticsInitiator - Statistics initialized [enabled=false]
3333 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'messageService'
3333 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'txManager'
3402 [main] INFO com.cypherf.TestSpringApplication - Running app...
3409 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [com.cypherf.repository.MessageRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
3409 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(1809269661<open>)] for JPA transaction
3409 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
3409 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - begin
3409 [main] DEBUG com.cypherf.repository.MessageRepository - Trying to save Message [id: 0; text:"Message one"]
3425 [main] DEBUG org.hibernate.SQL -
select
next value for Message_SEQ
Hibernate:
select
next value for Message_SEQ
3425 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 1
3440 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 1, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
3440 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction commit
3440 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [SessionImpl(1809269661<open>)]
3440 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - committing
3456 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3456 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3456 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(1809269661<open>)] after transaction
3456 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [com.cypherf.repository.MessageRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
3456 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(1553616699<open>)] for JPA transaction
3456 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
3456 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - begin
3456 [main] DEBUG com.cypherf.repository.MessageRepository - Trying to save Message [id: 0; text:"Message two"]
3456 [main] DEBUG org.hibernate.SQL -
select
next value for Message_SEQ
Hibernate:
select
next value for Message_SEQ
3456 [main] DEBUG org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 51
3456 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 2, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
3456 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction commit
3456 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [SessionImpl(1553616699<open>)]
3456 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - committing
3456 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3456 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3456 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(1553616699<open>)] after transaction
3456 [main] INFO com.cypherf.service.MessageService - MessageService.printAllMessages()
3456 [main] DEBUG org.hibernate.orm.query.hql - HQL : from Message
3724 [main] DEBUG org.hibernate.orm.query.sqm.ast - SqmStatement Tree :
-> [select]
-> [query-spec]
-> [select]
-> [selection]
-> [root] - `com.cypherf.model.Message(136820536837300)`
<- [root] - `com.cypherf.model.Message(136820536837300)`
<- [selection]
<- [select]
-> [from]
-> [root] - `com.cypherf.model.Message(136820536837300)`
<- [root] - `com.cypherf.model.Message(136820536837300)`
<- [from]
<- [query-spec]
<- [select]
3771 [main] DEBUG org.hibernate.orm.sql.ast.create - Created new SQL alias : m1_0
3771 [main] DEBUG org.hibernate.orm.sql.ast.create - Registration of TableGroup [StandardTableGroup(com.cypherf.model.Message(136820536837300))] with identifierForTableGroup [com.cypherf.model.Message] for NavigablePath [com.cypherf.model.Message]
3787 [main] DEBUG org.hibernate.orm.results.graph.AST - DomainResult Graph:
\-EntityResultImpl [com.cypherf.model.Message(136820536837300)]
| \-BasicFetch [com.cypherf.model.Message(136820536837300).text]
3787 [main] DEBUG org.hibernate.orm.sql.ast.tree - SQL AST Tree:
SelectStatement {
FromClause {
StandardTableGroup (m1 : com.cypherf.model.Message(136820536837300)) {
primaryTableReference : Message as m1_0
}
}
}
3803 [main] DEBUG org.hibernate.orm.sql.exec - Skipping reading Query result cache data: cache-enabled = false, cache-mode = NORMAL
3819 [main] DEBUG org.hibernate.orm.results - Initializer list
3819 [main] DEBUG org.hibernate.orm.results - com.cypherf.model.Message(136820536837300) -> EntityResultInitializer(com.cypherf.model.Message(136820536837300))@107577149 (SingleTableEntityPersister(com.cypherf.model.Message))
3819 [main] DEBUG org.hibernate.SQL -
select
m1_0.id,
m1_0.text
from
Message m1_0
Hibernate:
select
m1_0.id,
m1_0.text
from
Message m1_0
3819 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3819 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3819 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [com.cypherf.repository.MessageRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
3819 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [SessionImpl(225465790<open>)] for JPA transaction
3819 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
3819 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - begin
3819 [main] DEBUG com.cypherf.repository.MessageRepository - Trying to save Message [id: 0; text:"Message two"]
3834 [main] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 3, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
3834 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction commit
3834 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [SessionImpl(225465790<open>)]
3834 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - committing
3834 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3834 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3834 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(225465790<open>)] after transaction
3834 [main] INFO com.cypherf.service.MessageService - MessageService.printAllMessages()
3834 [main] DEBUG org.hibernate.orm.sql.exec - Skipping reading Query result cache data: cache-enabled = false, cache-mode = NORMAL
3834 [main] DEBUG org.hibernate.orm.results - Initializer list
3834 [main] DEBUG org.hibernate.orm.results - com.cypherf.model.Message(136820536837300) -> EntityResultInitializer(com.cypherf.model.Message(136820536837300))@1174086484 (SingleTableEntityPersister(com.cypherf.model.Message))
3834 [main] DEBUG org.hibernate.SQL -
select
m1_0.id,
m1_0.text
from
Message m1_0
Hibernate:
select
m1_0.id,
m1_0.text
from
Message m1_0
3834 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
3834 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.3/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 5s
3 actionable tasks: 2 executed, 1 up-to-date
13:29:27: Execution finished ':TestSpringApplication.main()'.
I finally made your code working on my local by fixing your code. :)
Now, it's persisting the data in the database. I have used mysql database for testing.
For testing, hibernate.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!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="show_sql">true</property>
<property name="format_sql">true</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">Anish@123</property>
<property name="hibernate.hbm2ddl.auto">create-drop</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.example.demo.Message"/>
</session-factory>
</hibernate-configuration>
Remove @EnableTransactionManagement
from the MessageRepository class, put @Transactional(transactionManager="txManager")
on the save
method and put @PersistenceContext
on the entityManager instead of @Autowired
:
package com.example.demo;
import jakarta.persistence.EntityManager;
import jakarta.persistence.NoResultException;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.repository.CrudRepository;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Repository
public class MessageRepository implements CrudRepository<Message, Long> {
@PersistenceContext
private EntityManager em;
private final static Logger logger = LoggerFactory.getLogger(MessageRepository.class);
@Transactional(transactionManager = "txManager")
@Override
public @NonNull <S extends Message> S save(@NonNull S message) {
//em.getTransaction().begin();
em.persist(message);
//em.getTransaction().commit();
return message;
}
....
}
Add @EnableTransactionManagement
on the PersistenceUtil and @Bean
over the EntityManagerFactory so that Spring is able to find the bean and inject in EntityManager via @PersistenceContext
:
package com.example.demo;
import jakarta.annotation.PreDestroy;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@Service
public class PersistenceUtil {
final static Logger logger = LoggerFactory.getLogger(PersistenceUtil.class);
private static EntityManagerFactory emf = null;
@Bean
public PlatformTransactionManager txManager() {
return new JpaTransactionManager(getEntityManagerFactory());
}
@Bean
public EntityManagerFactory getEntityManagerFactory() {
if (emf == null) {
synchronized (EntityManagerFactory.class) {
if (emf == null) {
final StandardServiceRegistry sr = new StandardServiceRegistryBuilder()
.configure() // Configures setting from hibernate.cfg.xml
.build();
try {
emf = new MetadataSources(sr).buildMetadata().buildSessionFactory();
}
catch (Exception e) {
StandardServiceRegistryBuilder.destroy(sr);
throw e;
}
}
}
}
return emf;
}
@PreDestroy
public static void closeEntityManagerFactory() {
System.out.println("PersistenceUtil.closeEntityManagerFactory()");
if (emf != null) {
emf.close();
}
}
@Bean
public EntityManager getEntityManager() {
return getEntityManagerFactory().createEntityManager();
}
}
TestSpringApplication:
@Configuration
@ComponentScan
public class TestSpringApplication {
@Autowired
private ApplicationContext context;
@Autowired
private CrudRepository<Message, Long> messageRepository;
final static Logger logger = LoggerFactory.getLogger(TestSpringApplication.class);
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(TestSpringApplication.class);
TestSpringApplication app = ctx.getBean(TestSpringApplication.class);
app.run(args);
}
public void run(String... args) {
// SAVE
logger.debug("saving message 1/one...");
Message messageOne = messageRepository.save(new Message("Message one"));
logger.debug("saving message 2/two...");
Message messageTwo = messageRepository.save(new Message("Message two"));
printAllMessages();
// SAVE ALL
logger.debug("saving message 2/two...");
Message messageThree = new Message("Message three");
Message messageFour = new Message("Message four");
Message messageFive = new Message("Message five");
Message messageSix = new Message("Message six");
Message messageSeven = new Message("Message seven");
Message messageEight = new Message("Message eight");
List<Message> messages = Arrays.asList(messageThree, messageFour, messageFive, messageSix, messageSeven, messageEight);
messageRepository.saveAll(messages);
// FIND ALL
printAllMessages();
}
private void printAllMessages() {
logger.debug("finding all messages...");
messageRepository.findAll().forEach(m -> {
logger.debug("Message: " + m.toString());
});
}
}
Successful data persistence with the screenshot: