Merge branch 'master' of github.com:eugenp/tutorials into master

This commit is contained in:
Karsten Silz 2020-09-03 17:07:08 +01:00
commit 0bb1851089
131 changed files with 943 additions and 3014 deletions

5
.gitignore vendored
View File

@ -87,4 +87,7 @@ transaction.log
apache-cxf/cxf-aegis/baeldung.xml
testing-modules/report-*.json
libraries-2/*.db
libraries-2/*.db
# SDKMan
.sdkmanrc

View File

@ -0,0 +1,14 @@
package com.baeldung.exceptions.illegalmonitorstate;
public class Data {
private String message;
public void send(String message) {
this.message = message;
}
public String receive() {
return message;
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.exceptions.illegalmonitorstate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SynchronizedReceiver implements Runnable {
private static Logger log = LoggerFactory.getLogger(SynchronizedReceiver.class);
private final Data data;
private String message;
private boolean illegalMonitorStateExceptionOccurred;
public SynchronizedReceiver(Data data) {
this.data = data;
}
@Override
public void run() {
synchronized (data) {
try {
data.wait();
this.message = data.receive();
} catch (InterruptedException e) {
log.error("thread was interrupted", e);
Thread.currentThread().interrupt();
} catch (IllegalMonitorStateException e) {
log.error("illegal monitor state exception occurred", e);
illegalMonitorStateExceptionOccurred = true;
}
}
}
public boolean hasIllegalMonitorStateExceptionOccurred() {
return illegalMonitorStateExceptionOccurred;
}
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.exceptions.illegalmonitorstate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SynchronizedSender implements Runnable {
private static Logger log = LoggerFactory.getLogger(SynchronizedSender.class);
private final Data data;
private boolean illegalMonitorStateExceptionOccurred;
public SynchronizedSender(Data data) {
this.data = data;
}
@Override
public void run() {
synchronized (data) {
try {
Thread.sleep(1000);
data.send("test");
data.notifyAll();
} catch (InterruptedException e) {
log.error("thread was interrupted", e);
Thread.currentThread().interrupt();
} catch (IllegalMonitorStateException e) {
log.error("illegal monitor state exception occurred", e);
illegalMonitorStateExceptionOccurred = true;
}
}
}
public boolean hasIllegalMonitorStateExceptionOccurred() {
return illegalMonitorStateExceptionOccurred;
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.exceptions.illegalmonitorstate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UnsynchronizedReceiver implements Runnable {
private static Logger log = LoggerFactory.getLogger(UnsynchronizedReceiver.class);
private final Data data;
private String message;
private boolean illegalMonitorStateExceptionOccurred;
public UnsynchronizedReceiver(Data data) {
this.data = data;
}
@Override
public void run() {
try {
data.wait();
this.message = data.receive();
} catch (InterruptedException e) {
log.error("thread was interrupted", e);
Thread.currentThread().interrupt();
} catch (IllegalMonitorStateException e) {
log.error("illegal monitor state exception occurred", e);
illegalMonitorStateExceptionOccurred = true;
}
}
public boolean hasIllegalMonitorStateExceptionOccurred() {
return illegalMonitorStateExceptionOccurred;
}
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.exceptions.illegalmonitorstate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UnsynchronizedSender implements Runnable {
private static Logger log = LoggerFactory.getLogger(UnsynchronizedSender.class);
private final Data data;
private boolean illegalMonitorStateExceptionOccurred;
public UnsynchronizedSender(Data data) {
this.data = data;
}
@Override
public void run() {
try {
Thread.sleep(1000);
data.send("test");
data.notifyAll();
} catch (InterruptedException e) {
log.error("thread was interrupted", e);
Thread.currentThread().interrupt();
} catch (IllegalMonitorStateException e) {
log.error("illegal monitor state exception occurred", e);
illegalMonitorStateExceptionOccurred = true;
}
}
public boolean hasIllegalMonitorStateExceptionOccurred() {
return illegalMonitorStateExceptionOccurred;
}
}

View File

@ -0,0 +1,70 @@
package com.baeldung.exceptions.illegalmonitorstate;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class IllegalMonitorStateExceptionUnitTest {
@Test
void whenSyncSenderAndSyncReceiverAreUsed_thenIllegalMonitorExceptionShouldNotBeThrown() throws InterruptedException {
Data data = new Data();
SynchronizedReceiver receiver = new SynchronizedReceiver(data);
Thread receiverThread = new Thread(receiver, "receiver-thread");
receiverThread.start();
SynchronizedSender sender = new SynchronizedSender(data);
Thread senderThread = new Thread(sender, "sender-thread");
senderThread.start();
senderThread.join(1000);
receiverThread.join(1000);
assertEquals("test", receiver.getMessage());
assertFalse(sender.hasIllegalMonitorStateExceptionOccurred());
assertFalse(receiver.hasIllegalMonitorStateExceptionOccurred());
}
@Test
void whenSyncSenderAndUnSyncReceiverAreUsed_thenIllegalMonitorExceptionShouldNotBeThrown() throws InterruptedException {
Data data = new Data();
UnsynchronizedReceiver receiver = new UnsynchronizedReceiver(data);
Thread receiverThread = new Thread(receiver, "receiver-thread");
receiverThread.start();
SynchronizedSender sender = new SynchronizedSender(data);
Thread senderThread = new Thread(sender, "sender-thread");
senderThread.start();
receiverThread.join(1000);
senderThread.join(1000);
assertNull(receiver.getMessage());
assertFalse(sender.hasIllegalMonitorStateExceptionOccurred());
assertTrue(receiver.hasIllegalMonitorStateExceptionOccurred());
}
@Test
void whenUnSyncSenderAndSyncReceiverAreUsed_thenIllegalMonitorExceptionShouldBeThrown() throws InterruptedException {
Data data = new Data();
SynchronizedReceiver receiver = new SynchronizedReceiver(data);
Thread receiverThread = new Thread(receiver, "receiver-thread");
receiverThread.start();
UnsynchronizedSender sender = new UnsynchronizedSender(data);
Thread senderThread = new Thread(sender, "sender-thread");
senderThread.start();
receiverThread.join(1000);
senderThread.join(1000);
assertNull(receiver.getMessage());
assertFalse(receiver.hasIllegalMonitorStateExceptionOccurred());
assertTrue(sender.hasIllegalMonitorStateExceptionOccurred());
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc.joins;
package com.baeldung.spring.jdbc.joins;
import java.sql.Connection;
import java.sql.ResultSet;

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc;
package com.baeldung.spring.jdbc;
import org.apache.log4j.Logger;
import org.junit.After;

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc;
package com.baeldung.spring.jdbc;
import static org.junit.Assert.assertEquals;

View File

@ -68,7 +68,9 @@
<module>spring-data-jpa-enterprise</module>
<module>spring-data-jpa-filtering</module>
<module>spring-data-jpa-query</module>
<module>spring-data-jpa-query-2</module>
<module>spring-data-jpa-repo</module>
<module>spring-data-jpa-repo-2</module>
<module>spring-data-jdbc</module>
@ -82,9 +84,9 @@
<module>spring-hibernate4</module>
<module>spring-jpa</module>
<module>spring-jpa-2</module>
<module>spring-jdbc</module>
<!-- <module>spring-mybatis</module> --> <!-- needs fixing in BAEL-9021 -->
<module>spring-persistence-simple</module>
<module>spring-persistence-simple-2</module>
</modules>
<properties>

View File

@ -4,6 +4,7 @@ This module contains articles about querying data using Spring Data JPA
### Relevant Articles:
- [Use Criteria Queries in a Spring Data Application](https://www.baeldung.com/spring-data-criteria-queries)
- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date)
- More articles: [[<-- prev]](../spring-data-jpa-query)
### Eclipse Config

View File

@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-data-jpa-query</artifactId>
<artifactId>spring-data-jpa-query-2</artifactId>
<name>spring-data-jpa-query-2</name>
<parent>

View File

@ -1,4 +1,4 @@
package com.baeldung.spring.data.persistence.model;
package com.baeldung.spring.data.jpa.query;
import javax.persistence.*;
import java.time.LocalDate;
@ -8,7 +8,6 @@ import java.util.Objects;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ -28,9 +27,6 @@ public class User {
private Integer status;
@OneToMany
List<Possession> possessionList;
public User() {
super();
}
@ -87,12 +83,20 @@ public class User {
return creationDate;
}
public List<Possession> getPossessionList() {
return possessionList;
public LocalDate getLastLoginDate() {
return lastLoginDate;
}
public void setPossessionList(List<Possession> possessionList) {
this.possessionList = possessionList;
public void setLastLoginDate(LocalDate lastLoginDate) {
this.lastLoginDate = lastLoginDate;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
@Override
@ -119,21 +123,4 @@ public class User {
public int hashCode() {
return Objects.hash(id, name, creationDate, age, email, status);
}
public LocalDate getLastLoginDate() {
return lastLoginDate;
}
public void setLastLoginDate(LocalDate lastLoginDate) {
this.lastLoginDate = lastLoginDate;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}

View File

@ -1,6 +1,5 @@
package com.baeldung.spring.data.persistence.repository;
package com.baeldung.spring.data.jpa.query;
import com.baeldung.spring.data.persistence.model.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@ -9,51 +8,16 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
public interface UserRepository extends JpaRepository<User, Integer>, UserRepositoryCustom {
Stream<User> findAllByName(String name);
@Query("SELECT u FROM User u WHERE u.status = 1")
Collection<User> findAllActiveUsers();
@Query("select u from User u where u.email like '%@gmail.com'")
List<User> findUsersWithGmailAddress();
@Query(value = "SELECT * FROM Users u WHERE u.status = 1", nativeQuery = true)
Collection<User> findAllActiveUsersNative();
@Query("SELECT u FROM User u WHERE u.status = ?1")
User findUserByStatus(Integer status);
@Query(value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true)
User findUserByStatusNative(Integer status);
@Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2")
User findUserByStatusAndName(Integer status, String name);
@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")
User findUserByStatusAndNameNamedParams(@Param("status") Integer status, @Param("name") String name);
@Query(value = "SELECT * FROM Users u WHERE u.status = :status AND u.name = :name", nativeQuery = true)
User findUserByStatusAndNameNamedParamsNative(@Param("status") Integer status, @Param("name") String name);
@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")
User findUserByUserStatusAndUserName(@Param("status") Integer userStatus, @Param("name") String userName);
@Query("SELECT u FROM User u WHERE u.name like ?1%")
User findUserByNameLike(String name);
@Query("SELECT u FROM User u WHERE u.name like :name%")
User findUserByNameLikeNamedParam(@Param("name") String name);
@Query(value = "SELECT * FROM users u WHERE u.name LIKE ?1%", nativeQuery = true)
User findUserByNameLikeNative(String name);
@Query(value = "SELECT u FROM User u")
List<User> findAllUsers(Sort sort);
@ -63,6 +27,27 @@ public interface UserRepository extends JpaRepository<User, Integer>, UserReposi
@Query(value = "SELECT * FROM Users ORDER BY id", countQuery = "SELECT count(*) FROM Users", nativeQuery = true)
Page<User> findAllUsersWithPaginationNative(Pageable pageable);
@Query("SELECT u FROM User u WHERE u.status = ?1")
User findUserByStatus(Integer status);
@Query("SELECT u FROM User u WHERE u.status = ?1 and u.name = ?2")
User findUserByStatusAndName(Integer status, String name);
@Query(value = "SELECT * FROM Users u WHERE u.status = ?1", nativeQuery = true)
User findUserByStatusNative(Integer status);
@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")
User findUserByStatusAndNameNamedParams(@Param("status") Integer status, @Param("name") String name);
@Query("SELECT u FROM User u WHERE u.status = :status and u.name = :name")
User findUserByUserStatusAndUserName(@Param("status") Integer userStatus, @Param("name") String userName);
@Query(value = "SELECT * FROM Users u WHERE u.status = :status AND u.name = :name", nativeQuery = true)
User findUserByStatusAndNameNamedParamsNative(@Param("status") Integer status, @Param("name") String name);
@Query(value = "SELECT u FROM User u WHERE u.name IN :names")
List<User> findUserByNameList(@Param("names") Collection<String> names);
@Modifying
@Query("update User u set u.status = :status where u.name = :name")
int updateUserSetStatusForName(@Param("status") Integer status, @Param("name") String name);
@ -74,25 +59,4 @@ public interface UserRepository extends JpaRepository<User, Integer>, UserReposi
@Query(value = "INSERT INTO Users (name, age, email, status, active) VALUES (:name, :age, :email, :status, :active)", nativeQuery = true)
@Modifying
void insertUser(@Param("name") String name, @Param("age") Integer age, @Param("email") String email, @Param("status") Integer status, @Param("active") boolean active);
@Modifying
@Query(value = "UPDATE Users u SET status = ? WHERE u.name = ?", nativeQuery = true)
int updateUserSetStatusForNameNativePostgres(Integer status, String name);
@Query(value = "SELECT u FROM User u WHERE u.name IN :names")
List<User> findUserByNameList(@Param("names") Collection<String> names);
void deleteAllByCreationDateAfter(LocalDate date);
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query("update User u set u.active = false where u.lastLoginDate < :date")
void deactivateUsersNotLoggedInSince(@Param("date") LocalDate date);
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query("delete User u where u.active = false")
int deleteDeactivatedUsers();
@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query(value = "alter table USERS add column deleted int(1) not null default 0", nativeQuery = true)
void addDeletedColumn();
}

View File

@ -1,6 +1,4 @@
package com.baeldung.spring.data.persistence.repository;
import com.baeldung.spring.data.persistence.model.User;
package com.baeldung.spring.data.jpa.query;
import java.util.Collection;
import java.util.List;

View File

@ -3,7 +3,6 @@
This module contains articles about querying data using Spring Data JPA
### Relevant Articles:
- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date)
- [The Exists Query in Spring Data](https://www.baeldung.com/spring-data-exists-query)
- [Customizing the Result of JPA Queries with Aggregation Functions](https://www.baeldung.com/jpa-queries-custom-result-with-aggregation-functions)
- [Limiting Query Results with JPA and Spring Data JPA](https://www.baeldung.com/jpa-limit-query-results)

View File

@ -0,0 +1,5 @@
## Spring Data JPA - Repositories
### Relevant Articles:
- [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa)
- More articles: [[<-- prev]](/spring-data-jpa-repo/)

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<artifactId>spring-data-jpa-repo-2</artifactId>
<name>spring-data-jpa-repo-2</name>
<dependencies>
<!-- Persistence -->
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- Utilities -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
<properties>
<guava.version>29.0-jre</guava.version>
</properties>
</project>

View File

@ -1,16 +1,10 @@
package com.baeldung.spring.data.persistence.model;
package com.baeldung.spring.data.persistence.repository;
import javax.persistence.*;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Foo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@ -28,8 +22,6 @@ public class Foo implements Serializable {
this.name = name;
}
// API
public long getId() {
return id;
}
@ -46,8 +38,6 @@ public class Foo implements Serializable {
this.name = name;
}
//
@Override
public int hashCode() {
final int prime = 31;
@ -79,5 +69,4 @@ public class Foo implements Serializable {
builder.append("Foo [name=").append(name).append("]");
return builder.toString();
}
}
}

View File

@ -0,0 +1,15 @@
package com.baeldung.spring.data.persistence.repository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class FooService implements IFooService {
@Autowired
private IFooDAO dao;
@Override
public Foo create(Foo foo) {
return dao.save(foo);
}
}

View File

@ -1,13 +1,13 @@
package com.baeldung.spring.data.persistence.repository;
import com.baeldung.spring.data.persistence.model.Foo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface IFooDao extends JpaRepository<Foo, Long> {
public interface IFooDAO extends JpaRepository<Foo, Long> {
Foo findByName(String name);
@Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)")
Foo retrieveByName(@Param("name") String name);
}

View File

@ -0,0 +1,5 @@
package com.baeldung.spring.data.persistence.repository;
public interface IFooService {
Foo create(Foo foo);
}

View File

@ -1,4 +1,4 @@
package com.baeldung.spring.data.persistence.config;
package com.baeldung.spring.data.persistence.repository;
import com.google.common.base.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
@ -20,11 +20,11 @@ import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@PropertySource("classpath:persistence.properties")
@ComponentScan("com.baeldung.spring.data.persistence.repository")
//@ImportResource("classpath*:*springDataConfig.xml")
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" })
@ComponentScan({ "com.baeldung.spring.data.persistence" })
//@ImportResource("classpath*:*springDataJpaRepositoriesConfig.xml")
@EnableJpaRepositories("com.baeldung.spring.data.persistence.repository")
@EnableJpaRepositories(basePackages = "com.baeldung.spring.data.persistence.repository")
public class PersistenceConfig {
@Autowired
@ -38,7 +38,7 @@ public class PersistenceConfig {
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan("com.baeldung.spring.data.persistence.model");
em.setPackagesToScan("com.baeldung.spring.data.persistence.repository");
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
@ -78,5 +78,4 @@ public class PersistenceConfig {
return hibernateProperties;
}
}
}

View File

@ -0,0 +1,3 @@
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

View File

@ -0,0 +1,9 @@
# jdbc.X
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jdbc.user=sa
jdbc.pass=
# hibernate.X
hibernate.hbm2ddl.auto=create-drop
hibernate.dialect=org.hibernate.dialect.H2Dialect

View File

@ -2,12 +2,10 @@
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
>
<jpa:repositories base-package="com.baeldung.spring.data.persistence.repository"/>
</beans>

View File

@ -0,0 +1,21 @@
package com.baeldung.spring.data.persistence.repository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = PersistenceConfig.class)
public class FooServiceIntegrationTest {
@Autowired
private IFooService service;
@Test(expected = DataIntegrityViolationException.class)
public final void whenInvalidEntityIsCreated_thenDataException() {
service.create(new Foo());
}
}

View File

@ -11,6 +11,7 @@ This module contains articles about repositories in Spring Data JPA
- [Spring Data Composable Repositories](https://www.baeldung.com/spring-data-composable-repositories)
- [Spring Data JPA Repository Populators](https://www.baeldung.com/spring-data-jpa-repository-populators)
- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures)
- More articles: [[--> next]](/spring-data-jpa-repo-2/)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:

View File

@ -0,0 +1,6 @@
## Spring JDBC
### Relevant Articles:
- [Spring JDBC Template](https://www.baeldung.com/spring-jdbc-jdbctemplate)
- [Spring JDBC Template Testing](https://www.baeldung.com/spring-jdbctemplate-testing)
- [Spring JDBC Template In Clause](https://www.baeldung.com/spring-jdbctemplate-in-list)

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<artifactId>spring-jdbc</artifactId>
<name>spring-jdbc</name>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jdbc</artifactId>
<version>${spring-data-jdbc.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<properties>
<spring-data-jdbc.version>2.0.3.RELEASE</spring-data-jdbc.version>
</properties>
</project>

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc.autogenkey.config;
package com.baeldung.spring.jdbc.autogenkey.config;
import javax.sql.DataSource;
@ -16,7 +16,7 @@ public class PersistenceConfig {
public DataSource dataSource(Environment env) {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("autogenkey-schema.sql")
.addScript("com/baeldung/spring/jdbc/autogenkey/autogenkey-schema.sql")
.build();
}

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc.autogenkey.repository;
package com.baeldung.spring.jdbc.autogenkey.repository;
import java.sql.PreparedStatement;

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc.autogenkey.repository;
package com.baeldung.spring.jdbc.autogenkey.repository;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc;
package com.baeldung.spring.jdbc.template.guide;
public class Employee {
private int id;

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc;
package com.baeldung.spring.jdbc.template.guide;
import java.sql.PreparedStatement;
import java.sql.SQLException;

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc;
package com.baeldung.spring.jdbc.template.guide;
import java.sql.ResultSet;
import java.sql.SQLException;

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc.config;
package com.baeldung.spring.jdbc.template.guide.config;
import javax.sql.DataSource;
@ -10,12 +10,16 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
@Configuration
@ComponentScan("com.baeldung.jdbc")
@ComponentScan("com.baeldung.spring.jdbc")
public class SpringJdbcConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:jdbc/schema.sql").addScript("classpath:jdbc/test-data.sql").build();
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:com/baeldung/spring/jdbc/template/guide/schema.sql")
.addScript("classpath:com/baeldung/spring/jdbc/template/guide/test-data.sql")
.build();
}
// @Bean

View File

@ -0,0 +1,42 @@
package com.baeldung.spring.jdbc.template.inclause;
public class Employee {
private int id;
private String firstName;
private String lastName;
public Employee(int id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public int getId() {
return id;
}
public void setId(final int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
}

View File

@ -1,10 +1,4 @@
package com.baeldung.jdbc;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.sql.DataSource;
package com.baeldung.spring.jdbc.template.inclause;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
@ -12,6 +6,11 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Repository
public class EmployeeDAO {
private JdbcTemplate jdbcTemplate;
@ -22,15 +21,11 @@ public class EmployeeDAO {
namedJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
public int getCountOfEmployees() {
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class);
}
public List<Employee> getEmployeesFromIdListNamed(List<Integer> ids) {
SqlParameterSource parameters = new MapSqlParameterSource("ids", ids);
List<Employee> employees = namedJdbcTemplate.query(
"SELECT * FROM EMPLOYEE WHERE id IN (:ids)",
parameters,
"SELECT * FROM EMPLOYEE WHERE id IN (:ids)",
parameters,
(rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name")));
return employees;
@ -39,8 +34,8 @@ public class EmployeeDAO {
public List<Employee> getEmployeesFromIdList(List<Integer> ids) {
String inSql = String.join(",", Collections.nCopies(ids.size(), "?"));
List<Employee> employees = jdbcTemplate.query(
String.format("SELECT * FROM EMPLOYEE WHERE id IN (%s)", inSql),
ids.toArray(),
String.format("SELECT * FROM EMPLOYEE WHERE id IN (%s)", inSql),
ids.toArray(),
(rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name")));
return employees;
@ -56,12 +51,11 @@ public class EmployeeDAO {
jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds);
List<Employee> employees = jdbcTemplate.query(
"SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)",
"SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)",
(rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name")));
jdbcTemplate.update("DELETE FROM employee_tmp");
return employees;
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc;
package com.baeldung.spring.jdbc.template.testing;
public class Employee {
private int id;

View File

@ -0,0 +1,19 @@
package com.baeldung.spring.jdbc.template.testing;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import javax.sql.DataSource;
@Repository
public class EmployeeDAO {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
public int getCountOfEmployees() {
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class);
}
}

View File

@ -0,0 +1,3 @@
spring.datasource.url=jdbc:mysql://localhost:3306/springjdbc
spring.datasource.username=guest_user
spring.datasource.password=guest_password

View File

@ -0,0 +1,7 @@
CREATE TABLE EMPLOYEE
(
ID int NOT NULL PRIMARY KEY,
FIRST_NAME varchar(255),
LAST_NAME varchar(255),
ADDRESS varchar(255)
);

View File

@ -0,0 +1,7 @@
INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling', 'Canada');
INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth', 'USA');
INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds', 'Finland');
INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie', 'USA');

View File

@ -0,0 +1,7 @@
CREATE TABLE EMPLOYEE
(
ID int NOT NULL PRIMARY KEY,
FIRST_NAME varchar(255),
LAST_NAME varchar(255),
ADDRESS varchar(255)
);

View File

@ -0,0 +1,7 @@
INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling', 'Canada');
INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth', 'USA');
INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds', 'Finland');
INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie', 'USA');

View File

@ -1,4 +1,4 @@
package com.baeldung.jdbc.autogenkey;
package com.baeldung.spring.jdbc.autogenkey;
import static org.junit.Assert.assertEquals;
@ -7,16 +7,17 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.jdbc.autogenkey.repository.MessageRepositoryJDBCTemplate;
import com.baeldung.jdbc.autogenkey.repository.MessageRepositorySimpleJDBCInsert;
import com.baeldung.spring.jdbc.autogenkey.repository.MessageRepositoryJDBCTemplate;
import com.baeldung.spring.jdbc.autogenkey.repository.MessageRepositorySimpleJDBCInsert;
@RunWith(SpringRunner.class)
public class GetAutoGenKeyByJDBC {
@Configuration
@ComponentScan(basePackages = { "com.baeldung.jdbc.autogenkey" })
@ComponentScan(basePackages = {"com.baeldung.spring.jdbc.autogenkey"})
public static class SpringConfig {
}
@ -35,7 +36,6 @@ public class GetAutoGenKeyByJDBC {
String loadedMessage = messageRepositoryJDBCTemplate.getMessageById(key);
assertEquals(MESSAGE_CONTENT, loadedMessage);
}
@Test

View File

@ -1,9 +1,11 @@
package com.baeldung.jdbc;
package com.baeldung.spring.jdbc.template.guide;
import java.util.ArrayList;
import java.util.List;
import com.baeldung.jdbc.config.SpringJdbcConfig;
import com.baeldung.spring.jdbc.template.guide.Employee;
import com.baeldung.spring.jdbc.template.guide.EmployeeDAO;
import com.baeldung.spring.jdbc.template.guide.config.SpringJdbcConfig;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@ -1,22 +1,19 @@
package com.baeldung.jdbc;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
package com.baeldung.spring.jdbc.template.inclause;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.test.util.ReflectionTestUtils;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
@RunWith(MockitoJUnitRunner.class)
@ -30,33 +27,9 @@ public class EmployeeDAOUnitTest {
public void setup() {
dataSource = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
.generateUniqueName(true)
.addScript("classpath:jdbc/schema.sql")
.addScript("classpath:jdbc/test-data.sql")
.addScript("classpath:com/baeldung/spring/jdbc/template/inclause/schema.sql")
.addScript("classpath:com/baeldung/spring/jdbc/template/inclause/test-data.sql")
.build();
}
@Test
public void whenMockJdbcTemplate_thenReturnCorrectEmployeeCount() {
EmployeeDAO employeeDAO = new EmployeeDAO();
ReflectionTestUtils.setField(employeeDAO, "jdbcTemplate", jdbcTemplate);
Mockito.when(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class))
.thenReturn(4);
assertEquals(4, employeeDAO.getCountOfEmployees());
Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Mockito.eq(Integer.class)))
.thenReturn(3);
assertEquals(3, employeeDAO.getCountOfEmployees());
}
@Test
public void whenInjectInMemoryDataSource_thenReturnCorrectEmployeeCount() {
EmployeeDAO employeeDAO = new EmployeeDAO();
employeeDAO.setDataSource(dataSource);
assertEquals(4, employeeDAO.getCountOfEmployees());
}
@Test

View File

@ -0,0 +1,56 @@
package com.baeldung.spring.jdbc.template.testing;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.test.util.ReflectionTestUtils;
import javax.sql.DataSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
@RunWith(MockitoJUnitRunner.class)
public class EmployeeDAOUnitTest {
@Mock
JdbcTemplate jdbcTemplate;
DataSource dataSource;
@Before
public void setup() {
dataSource = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
.generateUniqueName(true)
.addScript("classpath:com/baeldung/spring/jdbc/template/testing/schema.sql")
.addScript("classpath:com/baeldung/spring/jdbc/template/testing/test-data.sql")
.build();
}
@Test
public void whenMockJdbcTemplate_thenReturnCorrectEmployeeCount() {
EmployeeDAO employeeDAO = new EmployeeDAO();
ReflectionTestUtils.setField(employeeDAO, "jdbcTemplate", jdbcTemplate);
Mockito.when(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class))
.thenReturn(4);
assertEquals(4, employeeDAO.getCountOfEmployees());
Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Mockito.eq(Integer.class)))
.thenReturn(3);
assertEquals(3, employeeDAO.getCountOfEmployees());
}
@Test
public void whenInjectInMemoryDataSource_thenReturnCorrectEmployeeCount() {
EmployeeDAO employeeDAO = new EmployeeDAO();
employeeDAO.setDataSource(dataSource);
assertEquals(4, employeeDAO.getCountOfEmployees());
}
}

View File

@ -2,4 +2,9 @@
### Relevant Articles:
- [Many-To-Many Relationship in JPA](https://www.baeldung.com/jpa-many-to-many)
- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa)
- [Bootstrapping Hibernate 5 with Spring](https://www.baeldung.com/hibernate-5-spring)
- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring)
- [The DAO with Spring and Hibernate](https://www.baeldung.com/persistence-layer-with-spring-and-hibernate)
- [Simplify the DAO with Spring and Java Generics](https://www.baeldung.com/simplifying-the-data-access-layer-with-spring-and-java-generics)
- More articles: [[<-- prev]](/spring-jpa)

View File

@ -15,6 +15,17 @@
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
@ -43,8 +54,25 @@
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>${tomcat-dbcp.version}</version>
</dependency>
<!-- utilities -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
@ -57,6 +85,13 @@
<properties>
<!-- Spring -->
<org.springframework.version>5.1.5.RELEASE</org.springframework.version>
<!-- persistence -->
<tomcat-dbcp.version>9.0.0.M26</tomcat-dbcp.version>
<!-- utilities -->
<guava.version>21.0</guava.version>
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
</properties>
</project>

View File

@ -51,7 +51,7 @@ public class HibernateConf {
return transactionManager;
}
private final Properties hibernateProperties() {
private Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));

View File

@ -1,52 +1,49 @@
package com.baeldung.persistence.dao.common;
import java.io.Serializable;
import java.util.List;
package com.baeldung.spring.dao.generics;
import com.google.common.base.Preconditions;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.base.Preconditions;
import java.io.Serializable;
import java.util.List;
@SuppressWarnings("unchecked")
public abstract class AbstractHibernateDao<T extends Serializable> extends AbstractDao<T> implements IOperations<T> {
public abstract class AbstractHibernateDao<T extends Serializable> {
private Class<T> clazz;
@Autowired
protected SessionFactory sessionFactory;
// API
public void setClazz(final Class<T> clazzToSet) {
clazz = Preconditions.checkNotNull(clazzToSet);
}
@Override
// API
public T findOne(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
@Override
public List<T> findAll() {
return getCurrentSession().createQuery("from " + clazz.getName()).list();
}
@Override
public T create(final T entity) {
Preconditions.checkNotNull(entity);
getCurrentSession().saveOrUpdate(entity);
return entity;
}
@Override
public T update(final T entity) {
Preconditions.checkNotNull(entity);
return (T) getCurrentSession().merge(entity);
}
@Override
public void delete(final T entity) {
Preconditions.checkNotNull(entity);
getCurrentSession().delete(entity);
}
@Override
public void deleteById(final long entityId) {
final T entity = findOne(entityId);
Preconditions.checkState(entity != null);
@ -56,5 +53,4 @@ public abstract class AbstractHibernateDao<T extends Serializable> extends Abstr
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.jpa.dao;
package com.baeldung.spring.dao.generics;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@ -6,7 +6,6 @@ import java.io.Serializable;
import java.util.List;
public abstract class AbstractJpaDAO<T extends Serializable> {
private Class<T> clazz;
@PersistenceContext(unitName = "entityManagerFactory")
@ -42,5 +41,4 @@ public abstract class AbstractJpaDAO<T extends Serializable> {
final T entity = findOne(entityId);
delete(entity);
}
}

View File

@ -1,21 +1,10 @@
package com.baeldung.persistence.model;
import java.io.Serializable;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
package com.baeldung.spring.dao.generics;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.*;
import java.io.Serializable;
@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@ -41,18 +30,6 @@ public class Foo implements Serializable {
@Column(name = "NAME")
private String name;
@ManyToOne(targetEntity = Bar.class, fetch = FetchType.EAGER)
@JoinColumn(name = "BAR_ID")
private Bar bar;
public Bar getBar() {
return bar;
}
public void setBar(final Bar bar) {
this.bar = bar;
}
public Long getId() {
return id;
}
@ -100,5 +77,4 @@ public class Foo implements Serializable {
builder.append("Foo [name=").append(name).append("]");
return builder.toString();
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.spring.dao.generics;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class FooService implements IFooService {
IGenericDao<Foo> dao;
@Autowired
public void setDao(IGenericDao<Foo> daoToSet) {
dao = daoToSet;
dao.setClazz(Foo.class);
}
@Override
public Foo retrieveByName(String name) {
return null;
}
}

View File

@ -1,11 +1,11 @@
package com.baeldung.persistence.dao.common;
import java.io.Serializable;
package com.baeldung.spring.dao.generics;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import java.io.Serializable;
@Repository
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GenericHibernateDao<T extends Serializable> extends AbstractHibernateDao<T> implements IGenericDao<T> {

View File

@ -1,12 +1,10 @@
package com.baeldung.persistence.dao.common;
import java.io.Serializable;
package com.baeldung.spring.dao.generics;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import com.baeldung.jpa.dao.AbstractJpaDAO;
import java.io.Serializable;
@Repository
@Scope(BeanDefinition.SCOPE_PROTOTYPE)

View File

@ -0,0 +1,5 @@
package com.baeldung.spring.dao.generics;
public interface IFooService {
Foo retrieveByName(String name);
}

View File

@ -1,9 +1,10 @@
package com.baeldung.persistence.dao.common;
package com.baeldung.spring.dao.generics;
import java.io.Serializable;
import java.util.List;
public interface IOperations<T extends Serializable> {
public interface IGenericDao<T extends Serializable> {
void setClazz(Class< T > clazzToSet);
T findOne(final long id);
@ -16,5 +17,4 @@ public interface IOperations<T extends Serializable> {
void delete(final T entity);
void deleteById(final long entityId);
}

View File

@ -0,0 +1,56 @@
package com.baeldung.spring.hibernate;
import com.google.common.base.Preconditions;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
import java.util.List;
@SuppressWarnings("unchecked")
public abstract class AbstractHibernateDao<T extends Serializable> {
private Class<T> clazz;
@Autowired
protected SessionFactory sessionFactory;
protected final void setClazz(final Class<T> clazzToSet) {
clazz = Preconditions.checkNotNull(clazzToSet);
}
// API
public T findOne(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
public List<T> findAll() {
return getCurrentSession().createQuery("from " + clazz.getName()).list();
}
public T create(final T entity) {
Preconditions.checkNotNull(entity);
getCurrentSession().saveOrUpdate(entity);
return entity;
}
public T update(final T entity) {
Preconditions.checkNotNull(entity);
return (T) getCurrentSession().merge(entity);
}
public void delete(final T entity) {
Preconditions.checkNotNull(entity);
getCurrentSession().delete(entity);
}
public void deleteById(final long entityId) {
final T entity = findOne(entityId);
Preconditions.checkState(entity != null);
delete(entity);
}
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.spring.hibernate;
import javax.persistence.*;
import java.io.Serializable;
@Entity
public class Foo implements Serializable {
private static final long serialVersionUID = 1L;
public Foo() {
super();
}
public Foo(final String name) {
super();
this.name = name;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
private String name;
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}

View File

@ -1,14 +1,9 @@
package com.baeldung.hibernate.dao;
package com.baeldung.spring.hibernate;
import com.baeldung.persistence.model.Foo;
import org.springframework.stereotype.Repository;
import com.baeldung.jpa.dao.IFooDao;
import com.baeldung.persistence.dao.common.AbstractHibernateDao;
@Repository
public class FooDao extends AbstractHibernateDao<Foo> implements IFooDao {
public FooDao() {
super();
@ -16,5 +11,4 @@ public class FooDao extends AbstractHibernateDao<Foo> implements IFooDao {
}
// API
}

View File

@ -1,21 +1,15 @@
package com.baeldung.jpa.dao;
package com.baeldung.spring.hibernate;
import java.util.List;
import com.baeldung.persistence.model.Foo;
public interface IFooDao {
Foo findOne(long id);
List<Foo> findAll();
Foo create(Foo entity);
Foo update(Foo entity);
void delete(Foo entity);
void deleteById(long entityId);
}

View File

@ -1,9 +1,8 @@
package com.baeldung.config;
package com.baeldung.spring.jpa.guide;
import com.google.common.base.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
@ -21,17 +20,12 @@ import java.util.Properties;
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-h2.properties" })
@ComponentScan({ "com.baeldung.persistence","com.baeldung.jpa.dao" })
@PropertySource("classpath:persistence-h2.properties")
public class PersistenceJPAConfig {
@Autowired
private Environment env;
public PersistenceJPAConfig() {
super();
}
// beans
@Bean
@ -75,9 +69,7 @@ public class PersistenceJPAConfig {
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", "false");
return hibernateProperties;
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.spring.transaction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class FooService {}

View File

@ -0,0 +1,11 @@
# H2
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
# MySQL
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.username=mysqluser
#spring.datasource.password=mysqlpass
#spring.datasource.url=jdbc:mysql://localhost:3306/myDb?createDatabaseIfNotExist=true

View File

@ -6,7 +6,6 @@
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"
>
<context:property-placeholder location="classpath:persistence-h2.properties"/>
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
@ -14,8 +13,6 @@
<property name="packagesToScan" value="com.baeldung.persistence.model"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<!-- <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> <property name="generateDdl" value="${jpa.generateDdl}" /> <property name="databasePlatform"
value="${persistence.dialect}" /> </bean> -->
</property>
<property name="jpaProperties">
<props>

View File

@ -1,6 +0,0 @@
### Relevant Articles:
- [Spring JdbcTemplate Unit Testing](https://www.baeldung.com/spring-jdbctemplate-testing)
- [Using a List of Values in a JdbcTemplate IN Clause](https://www.baeldung.com/spring-jdbctemplate-in-list)
- [Transactional Annotations: Spring vs. JTA](https://www.baeldung.com/spring-vs-jta-transactional)
- [Test a Mock JNDI Datasource with Spring](https://www.baeldung.com/spring-mock-jndi-datasource)

View File

@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-persistence-simple-2</artifactId>
<version>0.1-SNAPSHOT</version>
<name>spring-persistence-simple-2</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>persistence-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- persistence -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>test</scope>
</dependency>
<!-- simple-jndi -->
<dependency>
<groupId>com.github.h-thurow</groupId>
<artifactId>simple-jndi</artifactId>
<version>${simple-jndi.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<!-- Spring -->
<org.springframework.version>5.2.4.RELEASE</org.springframework.version>
<!-- persistence -->
<h2.version>1.4.200</h2.version>
<!-- simple-jndi -->
<simple-jndi.version>0.23.0</simple-jndi.version>
<!-- test scoped -->
<mockito.version>3.3.3</mockito.version>
</properties>
</project>

View File

@ -1,6 +0,0 @@
CREATE TABLE EMPLOYEE
(
ID int NOT NULL PRIMARY KEY,
FIRST_NAME varchar(255),
LAST_NAME varchar(255)
);

View File

@ -1,4 +0,0 @@
INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling');
INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth');
INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds');
INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie');

View File

@ -4,15 +4,8 @@
### Relevant Articles:
- [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa)
- [Bootstrapping Hibernate 5 with Spring](http://www.baeldung.com/hibernate-5-spring)
- [The DAO with Spring and Hibernate](https://www.baeldung.com/persistence-layer-with-spring-and-hibernate)
- [Simplify the DAO with Spring and Java Generics](https://www.baeldung.com/simplifying-the-data-access-layer-with-spring-and-java-generics)
- [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring)
- [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa)
- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query)
- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate)
- [Transaction Propagation and Isolation in Spring @Transactional](https://www.baeldung.com/spring-transactional-propagation-isolation)
- [Mock JNDI Datasource](https://www.baeldung.com/spring-mock-jndi-datasource)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:

View File

@ -24,72 +24,23 @@
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- persistence -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>${jta.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${spring-data-jpa.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>${tomcat-dbcp.version}</version>
</dependency>
<!-- utils -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
<scope>test</scope>
</dependency>
<!-- simple-jndi -->
<dependency>
<groupId>com.github.h-thurow</groupId>
<artifactId>simple-jndi</artifactId>
<version>${simple-jndi.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
@ -97,56 +48,21 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>${apt-maven-plugin.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<!-- Spring -->
<org.springframework.version>5.2.6.RELEASE</org.springframework.version>
<org.springframework.version>5.2.4.RELEASE</org.springframework.version>
<!-- persistence -->
<hibernate.version>5.4.13.Final</hibernate.version>
<mysql-connector-java.version>8.0.19</mysql-connector-java.version>
<h2.version>1.4.200</h2.version>
<spring-data-jpa.version>2.2.7.RELEASE</spring-data-jpa.version>
<tomcat-dbcp.version>9.0.0.M26</tomcat-dbcp.version>
<jta.version>1.1</jta.version>
<querydsl.version>4.2.1</querydsl.version>
<!-- util -->
<guava.version>21.0</guava.version>
<assertj.version>3.8.0</assertj.version>
<apt-maven-plugin.version>1.1.3</apt-maven-plugin.version>
<!-- simple-jndi -->
<simple-jndi.version>0.23.0</simple-jndi.version>
<!-- test scoped -->
<mockito.version>3.3.3</mockito.version>
</properties>
</project>

View File

@ -1,110 +0,0 @@
package com.baeldung.config;
import com.baeldung.persistence.service.FooService;
import com.google.common.base.Preconditions;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@EnableTransactionManagement
@EnableJpaAuditing
@PropertySource({ "classpath:persistence-mysql.properties" })
@ComponentScan(basePackages = { "com.baeldung.persistence.dao", "com.baeldung.jpa.dao" })
public class PersistenceConfig {
@Autowired
private Environment env;
public PersistenceConfig() {
super();
}
@Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan("com.baeldung.persistence.model");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(restDataSource());
emf.setPackagesToScan("com.baeldung.persistence.model");
final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
emf.setJpaVendorAdapter(vendorAdapter);
emf.setJpaProperties(hibernateProperties());
return emf;
}
@Bean
public DataSource restDataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
@Bean
public PlatformTransactionManager hibernateTransactionManager() {
final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
@Bean
public PlatformTransactionManager jpaTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
@Bean
public FooService fooService() {
return new FooService();
}
private Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", "true");
// Envers properties
hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix"));
return hibernateProperties;
}
}

View File

@ -1,17 +0,0 @@
package com.baeldung.jpa.dao;
import com.baeldung.persistence.model.Foo;
import org.springframework.stereotype.Repository;
@Repository
public class FooDao extends AbstractJpaDAO<Foo> implements IFooDao {
public FooDao() {
super();
setClazz(Foo.class);
}
// API
}

View File

@ -1,14 +0,0 @@
package com.baeldung.persistence.dao.common;
import java.io.Serializable;
import com.google.common.base.Preconditions;
public abstract class AbstractDao<T extends Serializable> implements IOperations<T> {
protected Class<T> clazz;
protected final void setClazz(final Class<T> clazzToSet) {
clazz = Preconditions.checkNotNull(clazzToSet);
}
}

View File

@ -1,7 +0,0 @@
package com.baeldung.persistence.dao.common;
import java.io.Serializable;
public interface IGenericDao<T extends Serializable> extends IOperations<T> {
//
}

View File

@ -1,102 +0,0 @@
package com.baeldung.persistence.model;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
@Entity
public class Bar implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(nullable = false)
private String name;
@OneToMany(mappedBy = "bar", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@OrderBy("name ASC")
List<Foo> fooList;
public Bar() {
super();
}
public Bar(final String name) {
super();
this.name = name;
}
// API
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public List<Foo> getFooList() {
return fooList;
}
public void setFooList(final List<Foo> fooList) {
this.fooList = fooList;
}
//
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Bar other = (Bar) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Bar [name=").append(name).append("]");
return builder.toString();
}
}

View File

@ -1,36 +0,0 @@
package com.baeldung.persistence.service;
import java.util.List;
import com.baeldung.jpa.dao.IFooDao;
import com.baeldung.persistence.model.Foo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class FooService {
@Autowired
private IFooDao dao;
public FooService() {
super();
}
// API
public void create(final Foo entity) {
dao.create(entity);
}
public Foo findOne(final long id) {
return dao.findOne(id);
}
public List<Foo> findAll() {
return dao.findAll();
}
}

Some files were not shown because too many files have changed in this diff Show More