Hibernate has been used with spring for as long as I can remember. Now that spring boot and spring data have taken the game by storm spring boot with hibernate are no longer relevant. But just in case you are not too familiar with Spring data or you want to keep using hibernate the old school way. Here is how you can use hibernate with spring boot.
Step 1 – Create a spring boot project using spring initializr and make sure you include these dependencies.
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> </dependency>
Step 2 – Configure hibernate using java
@Configuration @EnableTransactionManagement public class HibernateConfig { @Bean public LocalSessionFactoryBean sessionFactory() { LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); sessionFactory.setHibernateProperties(hibernateProperties()); sessionFactory.setAnnotatedClasses(User.class, Role.class, Address.class); return sessionFactory; } private final Properties hibernateProperties() { final Properties hibernateProperties = new Properties(); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create"); hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect"); hibernateProperties.setProperty("hibernate.show_sql", "true"); hibernateProperties.setProperty("hibernate.format_sql", "true"); return hibernateProperties; } @Bean public DataSource dataSource() { Integer port = 3306; String host = "localhost"; String username = "root"; String password = ""; String dbName = "spring_boot_hibernate"; String url = "jdbc:mysql://" + host + ":" + port + "/" + dbName + "?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC"; return DataSourceBuilder.create().password(password).username(username).url(url).type(HikariDataSource.class) .build(); } @Bean public PlatformTransactionManager hibernateTransactionManager() { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(sessionFactory().getObject()); return transactionManager; } }
If you using a hibernate xml file, you can simply just import to your java hibernate class.
@Configuration @EnableTransactionManagement @ImportResource({"classpath:hibernateConfiguration.xml"}) public class HibernateConfig { // }
Step 3 – Create a DAO class for accessing the database.
@Repository public class UserDAO { private Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private SessionFactory sessionFactory; public User saveAndFlush(User user) { log.debug("saveAndFlush(..)"); Session session = sessionFactory.openSession(); Transaction transaction = session.getTransaction(); transaction.begin(); Object id = session.save(user); transaction.commit(); session.close(); log.debug("id={}",ObjectUtils.toJson(id)); user.setId((long)id); return user; } public User update(User user) { log.debug("update(..)"); Session session = sessionFactory.openSession(); Transaction transaction = session.getTransaction(); transaction.begin(); session.update(user); transaction.commit(); session.close(); return this.getById(user.getId()); } public User getById(Long memberId) { Session session = sessionFactory.openSession(); return session.get(User.class, memberId); } }
Just like that and you back in business with spring boot and hibernate. Springboot makes you life as a developer so much easier.
March 19, 2019Most springboot projects are going with either Hibernate, JPA, or Spring Data. If you are still using JDBC to communicate directly with the database then this tutorial is for you.
Step 1 – Add this dependency to your springboot project
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
Step 2 – Add your data source configuration to your application.properties file.
# database spring.datasource.url=jdbc:mysql://localhost:3306/spring_boot_jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password= spring.datasource.name=spring_boot_jdbc spring.datasource.driver-class-name=com.mysql.jdbc.Driver
Step 3 – Auto wire an instance of JdbcTemplate
@Autowired private JdbcTemplate jdbcTemplate;
Create a method to create tables.
public void setup() { jdbcTemplate.execute( "CREATE TABLE IF NOT EXISTS member(id bigint(20) NOT NULL AUTO_INCREMENT, email varchar(255) NOT NULL, password varchar(255) NOT NULL, uid varchar(255) NOT NULL, PRIMARY KEY (`id`))"); }
INSERT operation
public User create(User user) { StringBuilder query = new StringBuilder("INSERT INTO member(uid, email, password) VALUES (?, ?, ?)"); KeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(connection -> { PreparedStatement ps = connection.prepareStatement(query.toString(), Statement.RETURN_GENERATED_KEYS); ps.setString(1, user.getUid()); ps.setString(2, user.getEmail()); ps.setString(3, user.getPassword()); return ps; }, keyHolder); long id = keyHolder.getKey().longValue(); user.setId(id); return user; }
It is just that simple to get up and running with JdbcTemplate in springboot.
March 19, 2019Spring has events that can help facility functionalities of your application such as sending emails, calling a third party API, or processing an event asynchronously. The design pattern publisher and subscribers is exactly what spring boot events are.
First, create a spring event
To create a spring event, your event class has to extend the spring ApplicationEvent class. Here is an example of UserCreateEvent.
public class UserCreateEvent extends ApplicationEvent { private Logger log = LoggerFactory.getLogger(this.getClass()); public UserCreateEvent(User user) { super(user); log.info("UserCreateEvent, user={}", ObjectUtils.toJson(user)); } }
Second, create a publisher
A publisher has to be a spring bean. A publisher has to have a ApplicationEventPublisher field. You can create a method to call the publishEvent method on the ApplicationEventPublish class. Here is an example of a publisher.
@Component public class UserEventPublisher { private Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private ApplicationEventPublisher applicationEventPublisher; public void processUserCreate(User user) { UserCreateEvent userEvent = new UserCreateEvent(user); log.info("processUserCreate, userEvent={}",ObjectUtils.toJson(userEvent)); applicationEventPublisher.publishEvent(userEvent); } }
Lastly, create a listener
A spring event listener must be a spring bean. Anotate the event listener with @EventListener. There can be multiple listeners for an event. Listeners are by default synchronous. You can make listeners asychronous by adding @Async the method. Here is an example of a spring event listener.
@Component public class UserEventListener{ private Logger log = LoggerFactory.getLogger(this.getClass()); @Async @EventListener public void handleUserCreateEvent(UserCreateEvent createEvent) { log.info("handleUserCreateEvent, event={}",ObjectUtils.toJson(createEvent)); } }March 19, 2019
What is IoC or dependency injection?
IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method.
The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.
Container Overview
The org.springframework.context.ApplicationContext
interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans.
The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. It lets you express the objects that compose your application and the rich interdependencies between those objects.
The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the ApplicationContext
is created and initialized, you have a fully configured and executable system or application.
In stand-alone applications, it is common to create an instance of ClassPathXmlApplicationContext
or FileSystemXmlApplicationContext
. In a web application, you can add a simple web.xml for XML-based configuration or use @Configuration for Java-based configuration.
XML-based configuration
// create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance List<String> userList = service.getUsernameList();
The configuration metadata represents how you, as an application developer, tell the Spring container to instantiate, configure, and assemble the objects in your application.
There are 3 ways now to implement configuration metadata: XML based configuration, Java-based configuration, annotation-based configuration.
These days, developers prefer to use Java-based configuration for their projects.
Spring configuration consists of at least one and typically more than one bean definition that the container must manage. XML-based configuration metadata configures these beans as <bean/>
elements inside a top-level <beans/>
element. Java configuration typically uses @Bean
-annotated methods within a @Configuration
class.
The convention is to use the standard Java convention for instance field names when naming beans. That is, bean names start with a lowercase letter and are camel-cased from there. Examples of such names include accountManager
,accountService
, userDao
, loginController
, and so forth.
Naming beans consistently makes your configuration easier to read and understand. Also, if you use Spring AOP, it helps a lot when applying advice to a set of beans related by name.
Circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean. This means that, if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A.
@DependsOn – The depends-on
attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized.
By default, Spring eagerly instantiates all beans in the container when it starts up. But if needed you can lazy instantiate such beans so that they are created when they are first requested. However, when a lazy-initialized bean is a dependency of a singleton bean that is not lazy-initialized, Spring creates the lazy-initialized bean at startup, because it must satisfy the singleton’s dependencies. The lazy-initialized bean is injected into a singleton bean elsewhere that is not lazy-initialized.
March 19, 2019