Skip to content
This repository was archived by the owner on Jan 13, 2023. It is now read-only.

Commit 72b550e

Browse files
committed
Add Tx manager with JPA tutorial
1 parent 220b864 commit 72b550e

File tree

14 files changed

+283
-10
lines changed

14 files changed

+283
-10
lines changed

jpa-tx-management/pom.xml

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>spring-framework-tutorial</artifactId>
7+
<groupId>com.bobocode</groupId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>jpa-tx-management</artifactId>
13+
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>org.springframework</groupId>
18+
<artifactId>spring-orm</artifactId>
19+
<version>5.0.7.RELEASE</version>
20+
</dependency>
21+
<dependency>
22+
<groupId>com.h2database</groupId>
23+
<artifactId>h2</artifactId>
24+
<version>1.4.197</version>
25+
</dependency>
26+
<dependency>
27+
<groupId>org.slf4j</groupId>
28+
<artifactId>slf4j-simple</artifactId>
29+
<version>1.7.24</version>
30+
</dependency>
31+
<dependency>
32+
<groupId>org.hibernate.javax.persistence</groupId>
33+
<artifactId>hibernate-jpa-2.1-api</artifactId>
34+
<version>1.0.2.Final</version>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.hibernate</groupId>
38+
<artifactId>hibernate-core</artifactId>
39+
<version>5.3.2.Final</version>
40+
</dependency>
41+
42+
<!--Since JAXB APIs is no longer in default classpath in JDK 1.9 -->
43+
<dependency>
44+
<groupId>javax.xml.bind</groupId>
45+
<artifactId>jaxb-api</artifactId>
46+
<version>2.2.11</version>
47+
</dependency>
48+
49+
<dependency>
50+
<groupId>com.bobocode</groupId>
51+
<artifactId>spring-framework-tutorial-util</artifactId>
52+
<version>1.0-SNAPSHOT</version>
53+
</dependency>
54+
</dependencies>
55+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.bobocode;
2+
3+
import com.bobocode.config.RootConfig;
4+
import com.bobocode.model.Account;
5+
import com.bobocode.service.AccountService;
6+
import com.bobocode.util.TestDataGenerator;
7+
import org.springframework.context.ApplicationContext;
8+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
9+
10+
import java.math.BigDecimal;
11+
import java.util.List;
12+
13+
/**
14+
* This this code snipped shows Spring Transaction Manager with JPA example
15+
*/
16+
public class AccountApp {
17+
private static AccountService accountService;
18+
19+
public static void main(String[] args) {
20+
init();
21+
accountService.printAllAccounts();
22+
accountService.withdraw(1L, BigDecimal.valueOf(1_000_000));
23+
accountService.printAllAccounts();
24+
}
25+
26+
private static void init() {
27+
ApplicationContext context = new AnnotationConfigApplicationContext(RootConfig.class);
28+
accountService = context.getBean(AccountService.class);
29+
List<Account> accountList = TestDataGenerator.getAccountList(5);
30+
accountList.forEach(accountService::save);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.bobocode.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.Configuration;
5+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
6+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
7+
import org.springframework.orm.jpa.JpaVendorAdapter;
8+
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
9+
import org.springframework.orm.jpa.vendor.Database;
10+
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
11+
12+
import javax.sql.DataSource;
13+
14+
@Configuration
15+
public class JpaConfig {
16+
@Bean
17+
DataSource testDataSource() {
18+
return new EmbeddedDatabaseBuilder()
19+
.setType(EmbeddedDatabaseType.H2)
20+
.setName("bobocodeDB")
21+
.build();
22+
}
23+
24+
@Bean
25+
JpaVendorAdapter testJpaVendorAdapter() {
26+
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
27+
adapter.setDatabase(Database.H2);
28+
adapter.setShowSql(true);
29+
adapter.setGenerateDdl(true);
30+
adapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect");
31+
return adapter;
32+
}
33+
34+
@Bean("entityManagerFactory")
35+
LocalContainerEntityManagerFactoryBean localContainerEMF(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
36+
LocalContainerEntityManagerFactoryBean lcmfb = new LocalContainerEntityManagerFactoryBean();
37+
lcmfb.setDataSource(dataSource);
38+
lcmfb.setJpaVendorAdapter(jpaVendorAdapter);
39+
lcmfb.setPersistenceUnitName("bobocode");
40+
lcmfb.setPackagesToScan("com.bobocode.model");
41+
return lcmfb;
42+
}
43+
44+
// todo: instead of configuring previous three beans you can use file META-INF/persistence.xml and the following bean
45+
/*@Bean("entityManagerFactory")
46+
public LocalEntityManagerFactoryBean entityManagerFactoryBean() {
47+
LocalEntityManagerFactoryBean emfb = new LocalEntityManagerFactoryBean();
48+
emfb.setPersistenceUnitName("bobocode");
49+
return emfb;
50+
}*/
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.bobocode.config;
2+
3+
import org.springframework.context.annotation.Bean;
4+
import org.springframework.context.annotation.ComponentScan;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.orm.jpa.JpaTransactionManager;
7+
import org.springframework.transaction.PlatformTransactionManager;
8+
import org.springframework.transaction.annotation.EnableTransactionManagement;
9+
10+
import javax.persistence.EntityManagerFactory;
11+
12+
@Configuration
13+
@ComponentScan("com.bobocode")
14+
@EnableTransactionManagement
15+
public class RootConfig {
16+
@Bean
17+
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory){
18+
return new JpaTransactionManager(entityManagerFactory);
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.bobocode.dao;
2+
3+
import com.bobocode.model.Account;
4+
5+
import java.util.List;
6+
7+
public interface AccountDao {
8+
List<Account> findAll();
9+
10+
Account findById(long id);
11+
12+
void save(Account account);
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.bobocode.dao.impl;
2+
3+
import com.bobocode.dao.AccountDao;
4+
import com.bobocode.model.Account;
5+
import org.springframework.stereotype.Repository;
6+
import org.springframework.transaction.annotation.Transactional;
7+
8+
import javax.persistence.EntityManager;
9+
import javax.persistence.PersistenceContext;
10+
import java.util.List;
11+
12+
@Repository
13+
@Transactional
14+
public class JpaAccountDao implements AccountDao {
15+
@PersistenceContext
16+
private EntityManager entityManager;
17+
18+
@Override
19+
public List<Account> findAll() {
20+
return entityManager.createQuery("select a from Account a", Account.class).getResultList();
21+
}
22+
23+
@Override
24+
public Account findById(long id) {
25+
return entityManager.find(Account.class, id);
26+
}
27+
28+
@Override
29+
public void save(Account account) {
30+
entityManager.persist(account);
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.bobocode.service;
2+
3+
import com.bobocode.dao.AccountDao;
4+
import com.bobocode.model.Account;
5+
import org.springframework.stereotype.Service;
6+
import org.springframework.transaction.annotation.Transactional;
7+
8+
import java.math.BigDecimal;
9+
import java.util.List;
10+
11+
@Service
12+
@Transactional
13+
public class AccountService {
14+
private AccountDao accountDao;
15+
16+
public AccountService(AccountDao accountDao) {
17+
this.accountDao = accountDao;
18+
}
19+
20+
public void save(Account account) {
21+
accountDao.save(account);
22+
}
23+
24+
public void withdraw(long accountId, BigDecimal value) {
25+
Account account = accountDao.findById(accountId);
26+
account.setBalance(account.getBalance().add(value));
27+
}
28+
29+
@Transactional(readOnly = true)
30+
public void printAllAccounts() {
31+
List<Account> accounts = accountDao.findAll();
32+
accounts.forEach(System.out::println);
33+
}
34+
}

mvc-basics/src/main/java/com/bobocode/web/controller/WelcomeController.java

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.bobocode.web.controller;
22

33
import org.springframework.stereotype.Controller;
4+
import org.springframework.ui.Model;
45
import org.springframework.web.bind.annotation.GetMapping;
56

67
@Controller

mvc-basics/src/main/webapp/WEB-INF/views/welcome.jsp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
1+
Ú<%@ page contentType="text/html;charset=UTF-8" language="java" %>
22
<html>
33
<head>
44
<meta charset="UTF-8">

pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<module>aop-basics</module>
1717
<module>mvc-basics</module>
1818
<module>rest-basics</module>
19+
<module>jpa-tx-management</module>
1920
</modules>
2021

2122
<properties>
@@ -34,6 +35,11 @@
3435
<artifactId>spring-context</artifactId>
3536
<version>5.0.7.RELEASE</version>
3637
</dependency>
38+
<dependency>
39+
<groupId>org.springframework</groupId>
40+
<artifactId>spring-tx</artifactId>
41+
<version>5.0.7.RELEASE</version>
42+
</dependency>
3743
<dependency>
3844
<groupId>javax.annotation</groupId>
3945
<artifactId>javax.annotation-api</artifactId>

rest-basics/src/main/java/com/bobocode/web/controller/AccountRestController.java

-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,8 @@
33
import com.bobocode.model.Account;
44
import com.bobocode.service.AccountService;
55
import org.springframework.beans.factory.annotation.Autowired;
6-
import org.springframework.http.HttpHeaders;
7-
import org.springframework.http.HttpStatus;
86
import org.springframework.web.bind.annotation.*;
97

10-
import java.util.Collection;
118
import java.util.List;
129
import java.util.Objects;
1310

spring-framework-tutorial-model/pom.xml

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@
1111
</parent>
1212
<artifactId>spring-framework-tutorial-model</artifactId>
1313

14+
<dependencies>
15+
<dependency>
16+
<groupId>org.hibernate.javax.persistence</groupId>
17+
<artifactId>hibernate-jpa-2.1-api</artifactId>
18+
<version>1.0.2.Final</version>
19+
</dependency>
20+
<dependency>
21+
<groupId>org.hibernate</groupId>
22+
<artifactId>hibernate-core</artifactId>
23+
<version>5.3.2.Final</version>
24+
</dependency>
25+
</dependencies>
1426

1527

1628
</project>
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,43 @@
11
package com.bobocode.model;
22

3+
import com.bobocode.model.Gender;
34
import lombok.*;
45

6+
import javax.persistence.*;
57
import java.math.BigDecimal;
68
import java.time.LocalDate;
79
import java.time.LocalDateTime;
810

911
@NoArgsConstructor
10-
@Getter
11-
@Setter
12+
@Getter @Setter
1213
@ToString
1314
@EqualsAndHashCode(of = "email")
15+
@Entity
16+
@Table(name = "accounts")
1417
public class Account {
18+
@Id
19+
@GeneratedValue
1520
private Long id;
21+
22+
@Column(name = "first_name")
1623
private String firstName;
24+
25+
@Column(name = "last_name")
1726
private String lastName;
27+
28+
@Column(name = "email", unique = true)
1829
private String email;
30+
31+
@Column(name = "birthday")
1932
private LocalDate birthday;
33+
34+
@Column(name = "gender")
35+
@Enumerated(EnumType.STRING)
2036
private Gender gender;
21-
private LocalDateTime creationDate;
37+
38+
@Column(name = "creation_time")
39+
private LocalDateTime creationTime;
40+
41+
@Column(name = "balance")
2242
private BigDecimal balance = BigDecimal.ZERO;
2343
}

spring-framework-tutorial-util/src/main/java/com/bobocode/util/TestDataGenerator.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@ public static Account getAccount(){
115115
person.getDateOfBirth().getDayOfMonth()));
116116
fakeAccount.setGender(Gender.valueOf(person.getSex().name()));
117117
fakeAccount.setBalance(BigDecimal.valueOf(random.nextInt(200_000)));
118-
fakeAccount.setCreationDate(LocalDateTime.now());
118+
fakeAccount.setCreationTime(LocalDateTime.now());
119119

120120
return fakeAccount;
121121
}
122122

123123
public static List<Account> getAccountList(int size){
124-
return range(0, size)
125-
.mapToObj(i -> getAccount())
124+
return Stream.generate(TestDataGenerator::getAccount)
125+
.limit(size)
126126
.collect(toList());
127127
}
128128

0 commit comments

Comments
 (0)