From 4de59a4946088089f8dabe889fb4c2b4f54fbd8a Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 19 Mar 2023 13:32:11 -0400 Subject: [PATCH 1/4] Creating shallow copy vs deep copy in Java --- .../baeldung/shallowvsdeepcopy/Address.java | 58 +++++++++++++++++++ .../shallowvsdeepcopy/UserWithDeepClone.java | 49 ++++++++++++++++ .../UserWithShallowClone.java | 48 +++++++++++++++ .../shallowvsdeepcopy/UserCloneUnitTest.java | 23 ++++++++ 4 files changed, 178 insertions(+) create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java create mode 100644 core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java new file mode 100644 index 0000000000..a31e8d7e2d --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/Address.java @@ -0,0 +1,58 @@ +package com.baeldung.shallowvsdeepcopy; + +class Address implements Cloneable{ + + private String streetName; + private String zipCode; + private String cityName; + private String country; + + public Address(String streetName, String zipCode, String cityName, String country) { + this.streetName = streetName; + this.zipCode = zipCode; + this.cityName = cityName; + this.country = country; + } + + public String getStreetName() { + return streetName; + } + + public void setStreetName(String streetName) { + this.streetName = streetName; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public String getCityName() { + return cityName; + } + + public void setCityName(String cityName) { + this.cityName = cityName; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + @Override + public Address clone() { + try { + Address clone = (Address) super.clone(); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java new file mode 100644 index 0000000000..70646d396c --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithDeepClone.java @@ -0,0 +1,49 @@ +package com.baeldung.shallowvsdeepcopy; + +public class UserWithDeepClone implements Cloneable{ + + private String name; + private Address address; + private int age; + + public UserWithDeepClone(String name, Address address, int age) { + this.name = name; + this.address = address; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public UserWithDeepClone clone() { + try { + UserWithDeepClone clone = (UserWithDeepClone) super.clone(); + clone.setAddress(clone.getAddress().clone()); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java new file mode 100644 index 0000000000..19c9b55412 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/shallowvsdeepcopy/UserWithShallowClone.java @@ -0,0 +1,48 @@ +package com.baeldung.shallowvsdeepcopy; + +public class UserWithShallowClone implements Cloneable{ + + private String name; + private Address address; + private int age; + + public UserWithShallowClone(String name, Address address, int age) { + this.name = name; + this.address = address; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public UserWithShallowClone clone() { + try { + UserWithShallowClone clone = (UserWithShallowClone) super.clone(); + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java b/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java new file mode 100644 index 0000000000..f5a7d9df93 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/shallowvsdeepcopy/UserCloneUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.shallowvsdeepcopy; +import org.junit.Test; +import static org.assertj.core.api.Assertions.assertThat; + +public class UserCloneUnitTest { + + @Test + public void givenUser_WhenCopyCreated_thenCopyIsShallow(){ + Address address = new Address("abc", "444-0000", "pqr", "USA"); + UserWithShallowClone user = new UserWithShallowClone("baeldung", address,32); + + UserWithShallowClone userClone = (UserWithShallowClone)user.clone(); + assertThat(userClone.getAddress()).isEqualTo(user.getAddress()); + } + + @Test + public void givenUserWithDeepCloneMethod_WhenCopyCreated_thenCopyIsDeep(){ + Address address = new Address("abc", "444-0000", "pqr", "USA"); + UserWithDeepClone user = new UserWithDeepClone("baeldung", address,32); + UserWithDeepClone userClone = (UserWithDeepClone)user.clone(); + assertThat(userClone.getAddress()).isNotEqualTo(user.getAddress()); + } +} \ No newline at end of file From b52c5ed2bd4c7e5e2f08fe82faf99badfdca03c4 Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 14 May 2023 12:09:07 -0400 Subject: [PATCH 2/4] JPA Counting Row Implementation --- .../countrows/AccountStatsApplication.java | 11 ++ .../baeldung/countrows/entity/Account.java | 96 ++++++++++++ .../baeldung/countrows/entity/Permission.java | 39 +++++ .../repository/AccountRepository.java | 22 +++ .../repository/PermissionRepository.java | 12 ++ .../countrows/service/AccountStatsLogic.java | 123 +++++++++++++++ .../AccountStatsUnitTests.java | 147 ++++++++++++++++++ 7 files changed, 450 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java create mode 100644 persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java new file mode 100644 index 0000000000..f5a99f0ad8 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/AccountStatsApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.countrows; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AccountStatsApplication { + public static void main(String[] args) { + SpringApplication.run(AccountStatsApplication.class, args); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java new file mode 100644 index 0000000000..11e4cb412e --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java @@ -0,0 +1,96 @@ +package com.baeldung.countrows.entity; + +import javax.persistence.*; + +import java.security.PrivateKey; +import java.sql.Timestamp; +import java.time.Instant; +import java.util.Date; + +@Entity +@Table(name="ACCOUNTS") +public class Account { + @Id + @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "accounts_seq") + @SequenceGenerator(name = "accounts_seq", sequenceName = "accounts_seq", allocationSize = 1) + @Column(name = "user_id") + private int userId; + private String username; + private String password; + private String email; + private Timestamp createdOn; + private Timestamp lastLogin; + + @OneToOne + @JoinColumn(name = "permissions_id") + private Permission permission; + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Timestamp getCreatedOn() { + return createdOn; + } + + public void setCreatedOn(Timestamp createdOn) { + this.createdOn = createdOn; + } + + public Timestamp getLastLogin() { + return lastLogin; + } + + public void setLastLogin(Timestamp lastLogin) { + this.lastLogin = lastLogin; + } + + public Permission getPermission() { + return permission; + } + + public void setPermission(Permission permission) { + this.permission = permission; + } + + @Override + public String toString() { + return "Account{" + + "userId=" + userId + + ", username='" + username + '\'' + + ", password='" + password + '\'' + + ", email='" + email + '\'' + + ", createdOn=" + createdOn + + ", lastLogin=" + lastLogin + + ", permission=" + permission + + '}'; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java new file mode 100644 index 0000000000..17e8ab9c12 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java @@ -0,0 +1,39 @@ +package com.baeldung.countrows.entity; + +import javax.persistence.*; + +@Entity +@Table(name="PERMISSIONS") +public class Permission { + + @Id + @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "permissions_id_sq") + @SequenceGenerator(name = "permissions_id_sq", sequenceName = "permissions_id_sq", allocationSize = 1) + private int id; + + private String type; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @Override + public String toString() { + return "Permission{" + + "id=" + id + + ", type='" + type + '\'' + + '}'; + } +} diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java new file mode 100644 index 0000000000..875a2e7160 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java @@ -0,0 +1,22 @@ +package com.baeldung.countrows.repository; + +import com.baeldung.countrows.entity.Account; +import com.baeldung.countrows.entity.Permission; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.sql.Timestamp; +import java.util.Date; +import java.util.List; + +@Repository +public interface AccountRepository extends JpaRepository { + + long countByUsername(String username); + + long countByPermission(Permission permission); + + long countByPermissionAndCreatedOnGreaterThan(Permission permission, Timestamp ts); +} diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java new file mode 100644 index 0000000000..5e598b52ef --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/PermissionRepository.java @@ -0,0 +1,12 @@ +package com.baeldung.countrows.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.baeldung.countrows.entity.Permission; + +@Repository +public interface PermissionRepository extends JpaRepository { + Permission findByType(String type); +} + diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java new file mode 100644 index 0000000000..f8f8d5905e --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java @@ -0,0 +1,123 @@ +package com.baeldung.countrows.service; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.criteria.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.baeldung.countrows.entity.Account; +import com.baeldung.countrows.entity.Permission; +import com.baeldung.countrows.repository.AccountRepository; +import com.baeldung.countrows.repository.PermissionRepository; + +@Service +public class AccountStatsLogic { + @Autowired + private AccountRepository accountRepository; + + @PersistenceContext + private EntityManager entityManager; + + @Autowired + private PermissionRepository permissionRepository; + + public long getAccountCount(){ + return accountRepository.count(); + } + + public long getAccountCountByUsername(String username){ + return accountRepository.countByUsername(username); + } + + public long getAccountCountByPermission(Permission permission){ + return accountRepository.countByPermission(permission); + } + + + public long getAccountCountByPermissionAndCreatedOn(Permission permission, Date date) throws ParseException { + return accountRepository.countByPermissionAndCreatedOnGreaterThan(permission, new Timestamp(date.getTime())); + } + + public long getAccountsUsingCQ() throws ParseException { + // creating criteria builder and query + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = builder.createQuery(Long.class); + Root accountRoot = criteriaQuery.from(Account.class); + + // select query + criteriaQuery + .select(builder.count(accountRoot)); + + // execute and get the result + return entityManager.createQuery(criteriaQuery).getSingleResult(); + } + + public long getAccountsByPermissionUsingCQ(Permission permission) throws ParseException { + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = builder.createQuery(Long.class); + Root accountRoot = criteriaQuery.from(Account.class); + + List predicateList = new ArrayList<>(); // list of predicates that will go in where clause + predicateList.add(builder.equal(accountRoot.get("permission"), permission)); + + criteriaQuery + .select(builder.count(accountRoot)) + .where(builder.and(predicateList.toArray(new Predicate[0]))); + + return entityManager.createQuery(criteriaQuery).getSingleResult(); + } + + public long getAccountsByPermissionAndCreateOnUsingCQ(Permission permission, Date date) throws ParseException { + // creating criteria builder and query + CriteriaBuilder builder = entityManager.getCriteriaBuilder(); // create builder + CriteriaQuery criteriaQuery = builder.createQuery(Long.class);// query instance + Root accountRoot = criteriaQuery.from(Account.class); // root instance + + // list of predicates that will go in where clause + List predicateList = new ArrayList<>(); + predicateList.add(builder.equal(accountRoot.get("permission"), permission)); + predicateList.add(builder.greaterThan(accountRoot.get("createdOn"), new Timestamp(date.getTime()))); + + // select query + criteriaQuery + .select(builder.count(accountRoot)) + .where(builder.and(predicateList.toArray(new Predicate[0]))); + + // execute and get the result + return entityManager.createQuery(criteriaQuery).getSingleResult(); + } + + public long getAccountsUsingJPQL() throws ParseException { + Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a"); + return (long) query.getSingleResult(); + } + + public long getAccountsByPermissionUsingJPQL(Permission permission) throws ParseException { + Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a WHERE a.permission = ?1"); + query.setParameter(1, permission); + return (long) query.getSingleResult(); + } + + public long getAccountsByPermissionAndCreatedOnUsingJPQL(Permission permission, Date date) throws ParseException { + Query query = entityManager.createQuery("SELECT COUNT(*) FROM Account a WHERE a.permission = ?1 and a.createdOn > ?2"); + query.setParameter(1, permission); + query.setParameter(2, new Timestamp(date.getTime())); + return (long) query.getSingleResult(); + } + + private static Date getDate() throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date parsedDate = dateFormat.parse("2023-04-29"); + + System.out.println("parseDate: "+parsedDate); + return parsedDate; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java new file mode 100644 index 0000000000..2be8e910d9 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java @@ -0,0 +1,147 @@ +package com.baeldung.boot.countrows.accountstatslogic; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Date; +import java.util.UUID; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.baeldung.countrows.AccountStatsApplication; +import com.baeldung.countrows.entity.Account; +import com.baeldung.countrows.entity.Permission; +import com.baeldung.countrows.repository.AccountRepository; +import com.baeldung.countrows.repository.PermissionRepository; +import com.baeldung.countrows.service.AccountStatsLogic; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +@SpringBootTest(classes = AccountStatsApplication.class) +class AccountStatsUnitTests { + + @Autowired + private PermissionRepository permissionRepository; + + @Autowired + private AccountRepository accountRepository; + + @Autowired + private AccountStatsLogic accountStatsLogic; + + @AfterEach + public void afterEach(){ + accountRepository.deleteAll(); + permissionRepository.deleteAll(); + } + + @Test + public void givenAccountInTable_whenPerformCount_returnsAppropriateCount(){ + savePermissions(); + Account account = saveAccount(); + assertThat(accountStatsLogic.getAccountCount()).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByUsernameOrPermission_returnsAppropriateCount() { + savePermissions(); + Account account = saveAccount(); + assertThat(accountStatsLogic.getAccountCountByUsername(account.getUsername())).isEqualTo(1); + assertThat(accountStatsLogic.getAccountCountByPermission(account.getPermission())).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOn_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountCountByPermissionAndCreatedOn(account.getPermission(), account.getCreatedOn()); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountUsingCQ_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsUsingCQ(); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByPermissionUsingCQ_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionUsingCQ(account.getPermission()); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOnUsingCQ_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionAndCreateOnUsingCQ(account.getPermission(), account.getCreatedOn()); + assertThat(count).isEqualTo(1); + } + + @Test + public void givenAccountInTable_whenPerformCountUsingJPQL_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsUsingJPQL(); + assertThat(count).isEqualTo(1); + } + @Test + public void givenAccountInTable_whenPerformCountByPermissionUsingJPQL_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionUsingJPQL(account.getPermission()); + assertThat(count).isEqualTo(1); + } + @Test + public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOnUsingJPQL_returnsAppropriateCount() throws ParseException { + savePermissions(); + Account account = saveAccount(); + long count = accountStatsLogic.getAccountsByPermissionAndCreatedOnUsingJPQL(account.getPermission(), account.getCreatedOn()); + assertThat(count).isEqualTo(1); + } + + private Account saveAccount(){ + return accountRepository.save(getAccount()); + } + + private void savePermissions(){ + Permission editor = new Permission(); + editor.setType("editor"); + permissionRepository.save(editor); + + Permission admin = new Permission(); + admin.setType("admin"); + permissionRepository.save(admin); + } + + private static Date getDate() throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + Date parsedDate = dateFormat.parse("2023-04-29"); + return parsedDate; + } + + private Account getAccount() { + Permission permission = permissionRepository.findByType("admin"); + Account account = new Account(); + String seed = UUID.randomUUID().toString(); + account.setUsername("username_"+seed); + account.setEmail("username_"+seed+"@gmail.com"); + account.setPermission(permission); + account.setPassword("password_q1234"); + account.setCreatedOn(Timestamp.from(Instant.now())); + account.setLastLogin(Timestamp.from(Instant.now())); + return account; + } +} From 255601afb93f50d93ab190cb3d2185716d25c8b0 Mon Sep 17 00:00:00 2001 From: technoddy Date: Sun, 14 May 2023 12:38:41 -0400 Subject: [PATCH 3/4] updating class name for tests to abide by policy --- ...{AccountStatsUnitTests.java => AccountStatsUnitTest.java} | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) rename persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/{AccountStatsUnitTests.java => AccountStatsUnitTest.java} (96%) diff --git a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java similarity index 96% rename from persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java rename to persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java index 2be8e910d9..98269547c3 100644 --- a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTests.java +++ b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java @@ -10,8 +10,6 @@ import java.util.Date; import java.util.UUID; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.baeldung.countrows.AccountStatsApplication; @@ -23,10 +21,9 @@ import com.baeldung.countrows.service.AccountStatsLogic; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; @SpringBootTest(classes = AccountStatsApplication.class) -class AccountStatsUnitTests { +class AccountStatsUnitTest { @Autowired private PermissionRepository permissionRepository; From 69e5e519277289985e7f53e7e5d1453b6520ef96 Mon Sep 17 00:00:00 2001 From: technoddy Date: Thu, 25 May 2023 23:40:16 -0400 Subject: [PATCH 4/4] Addressing PR feedback --- .../baeldung/countrows/entity/Account.java | 34 ++---------------- .../baeldung/countrows/entity/Permission.java | 21 ++--------- .../repository/AccountRepository.java | 1 + .../countrows/service/AccountStatsLogic.java | 35 ++++++++----------- .../AccountStatsUnitTest.java | 29 +++++++-------- 5 files changed, 34 insertions(+), 86 deletions(-) diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java index 11e4cb412e..d422c30a0e 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Account.java @@ -8,10 +8,10 @@ import java.time.Instant; import java.util.Date; @Entity -@Table(name="ACCOUNTS") +@Table(name = "ACCOUNTS") public class Account { @Id - @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "accounts_seq") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accounts_seq") @SequenceGenerator(name = "accounts_seq", sequenceName = "accounts_seq", allocationSize = 1) @Column(name = "user_id") private int userId; @@ -25,14 +25,6 @@ public class Account { @JoinColumn(name = "permissions_id") private Permission permission; - public int getUserId() { - return userId; - } - - public void setUserId(int userId) { - this.userId = userId; - } - public String getUsername() { return username; } @@ -41,18 +33,10 @@ public class Account { this.username = username; } - public String getPassword() { - return password; - } - public void setPassword(String password) { this.password = password; } - public String getEmail() { - return email; - } - public void setEmail(String email) { this.email = email; } @@ -65,10 +49,6 @@ public class Account { this.createdOn = createdOn; } - public Timestamp getLastLogin() { - return lastLogin; - } - public void setLastLogin(Timestamp lastLogin) { this.lastLogin = lastLogin; } @@ -83,14 +63,6 @@ public class Account { @Override public String toString() { - return "Account{" + - "userId=" + userId + - ", username='" + username + '\'' + - ", password='" + password + '\'' + - ", email='" + email + '\'' + - ", createdOn=" + createdOn + - ", lastLogin=" + lastLogin + - ", permission=" + permission + - '}'; + return "Account{" + "userId=" + userId + ", username='" + username + '\'' + ", password='" + password + '\'' + ", email='" + email + '\'' + ", createdOn=" + createdOn + ", lastLogin=" + lastLogin + ", permission=" + permission + '}'; } } \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java index 17e8ab9c12..9acedf0558 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/entity/Permission.java @@ -3,37 +3,22 @@ package com.baeldung.countrows.entity; import javax.persistence.*; @Entity -@Table(name="PERMISSIONS") +@Table(name = "PERMISSIONS") public class Permission { @Id - @GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "permissions_id_sq") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "permissions_id_sq") @SequenceGenerator(name = "permissions_id_sq", sequenceName = "permissions_id_sq", allocationSize = 1) private int id; private String type; - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getType() { - return type; - } - public void setType(String type) { this.type = type; } @Override public String toString() { - return "Permission{" + - "id=" + id + - ", type='" + type + '\'' + - '}'; + return "Permission{" + "id=" + id + ", type='" + type + '\'' + '}'; } } diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java index 875a2e7160..422962ce45 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/repository/AccountRepository.java @@ -2,6 +2,7 @@ package com.baeldung.countrows.repository; import com.baeldung.countrows.entity.Account; import com.baeldung.countrows.entity.Permission; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java index f8f8d5905e..e4e716b4ce 100644 --- a/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java +++ b/persistence-modules/spring-boot-persistence-3/src/main/java/com/baeldung/countrows/service/AccountStatsLogic.java @@ -11,8 +11,10 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.criteria.*; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; + import com.baeldung.countrows.entity.Account; import com.baeldung.countrows.entity.Permission; import com.baeldung.countrows.repository.AccountRepository; @@ -29,19 +31,18 @@ public class AccountStatsLogic { @Autowired private PermissionRepository permissionRepository; - public long getAccountCount(){ + public long getAccountCount() { return accountRepository.count(); } - public long getAccountCountByUsername(String username){ + public long getAccountCountByUsername(String username) { return accountRepository.countByUsername(username); } - public long getAccountCountByPermission(Permission permission){ + public long getAccountCountByPermission(Permission permission) { return accountRepository.countByPermission(permission); } - public long getAccountCountByPermissionAndCreatedOn(Permission permission, Date date) throws ParseException { return accountRepository.countByPermissionAndCreatedOnGreaterThan(permission, new Timestamp(date.getTime())); } @@ -53,11 +54,11 @@ public class AccountStatsLogic { Root accountRoot = criteriaQuery.from(Account.class); // select query - criteriaQuery - .select(builder.count(accountRoot)); + criteriaQuery.select(builder.count(accountRoot)); // execute and get the result - return entityManager.createQuery(criteriaQuery).getSingleResult(); + return entityManager.createQuery(criteriaQuery) + .getSingleResult(); } public long getAccountsByPermissionUsingCQ(Permission permission) throws ParseException { @@ -68,11 +69,11 @@ public class AccountStatsLogic { List predicateList = new ArrayList<>(); // list of predicates that will go in where clause predicateList.add(builder.equal(accountRoot.get("permission"), permission)); - criteriaQuery - .select(builder.count(accountRoot)) + criteriaQuery.select(builder.count(accountRoot)) .where(builder.and(predicateList.toArray(new Predicate[0]))); - return entityManager.createQuery(criteriaQuery).getSingleResult(); + return entityManager.createQuery(criteriaQuery) + .getSingleResult(); } public long getAccountsByPermissionAndCreateOnUsingCQ(Permission permission, Date date) throws ParseException { @@ -87,12 +88,12 @@ public class AccountStatsLogic { predicateList.add(builder.greaterThan(accountRoot.get("createdOn"), new Timestamp(date.getTime()))); // select query - criteriaQuery - .select(builder.count(accountRoot)) + criteriaQuery.select(builder.count(accountRoot)) .where(builder.and(predicateList.toArray(new Predicate[0]))); // execute and get the result - return entityManager.createQuery(criteriaQuery).getSingleResult(); + return entityManager.createQuery(criteriaQuery) + .getSingleResult(); } public long getAccountsUsingJPQL() throws ParseException { @@ -112,12 +113,4 @@ public class AccountStatsLogic { query.setParameter(2, new Timestamp(date.getTime())); return (long) query.getSingleResult(); } - - private static Date getDate() throws ParseException { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date parsedDate = dateFormat.parse("2023-04-29"); - - System.out.println("parseDate: "+parsedDate); - return parsedDate; - } } \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java index 98269547c3..af825601aa 100644 --- a/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java +++ b/persistence-modules/spring-boot-persistence-3/src/test/java/com/baeldung/boot/countrows/accountstatslogic/AccountStatsUnitTest.java @@ -35,15 +35,15 @@ class AccountStatsUnitTest { private AccountStatsLogic accountStatsLogic; @AfterEach - public void afterEach(){ + public void afterEach() { accountRepository.deleteAll(); permissionRepository.deleteAll(); } @Test - public void givenAccountInTable_whenPerformCount_returnsAppropriateCount(){ + public void givenAccountInTable_whenPerformCount_returnsAppropriateCount() { savePermissions(); - Account account = saveAccount(); + saveAccount(); assertThat(accountStatsLogic.getAccountCount()).isEqualTo(1); } @@ -66,7 +66,7 @@ class AccountStatsUnitTest { @Test public void givenAccountInTable_whenPerformCountUsingCQ_returnsAppropriateCount() throws ParseException { savePermissions(); - Account account = saveAccount(); + saveAccount(); long count = accountStatsLogic.getAccountsUsingCQ(); assertThat(count).isEqualTo(1); } @@ -90,10 +90,11 @@ class AccountStatsUnitTest { @Test public void givenAccountInTable_whenPerformCountUsingJPQL_returnsAppropriateCount() throws ParseException { savePermissions(); - Account account = saveAccount(); + saveAccount(); long count = accountStatsLogic.getAccountsUsingJPQL(); assertThat(count).isEqualTo(1); } + @Test public void givenAccountInTable_whenPerformCountByPermissionUsingJPQL_returnsAppropriateCount() throws ParseException { savePermissions(); @@ -101,6 +102,7 @@ class AccountStatsUnitTest { long count = accountStatsLogic.getAccountsByPermissionUsingJPQL(account.getPermission()); assertThat(count).isEqualTo(1); } + @Test public void givenAccountInTable_whenPerformCountByPermissionAndCreatedOnUsingJPQL_returnsAppropriateCount() throws ParseException { savePermissions(); @@ -109,11 +111,11 @@ class AccountStatsUnitTest { assertThat(count).isEqualTo(1); } - private Account saveAccount(){ + private Account saveAccount() { return accountRepository.save(getAccount()); } - private void savePermissions(){ + private void savePermissions() { Permission editor = new Permission(); editor.setType("editor"); permissionRepository.save(editor); @@ -123,18 +125,13 @@ class AccountStatsUnitTest { permissionRepository.save(admin); } - private static Date getDate() throws ParseException { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date parsedDate = dateFormat.parse("2023-04-29"); - return parsedDate; - } - private Account getAccount() { Permission permission = permissionRepository.findByType("admin"); Account account = new Account(); - String seed = UUID.randomUUID().toString(); - account.setUsername("username_"+seed); - account.setEmail("username_"+seed+"@gmail.com"); + String seed = UUID.randomUUID() + .toString(); + account.setUsername("username_" + seed); + account.setEmail("username_" + seed + "@gmail.com"); account.setPermission(permission); account.setPassword("password_q1234"); account.setCreatedOn(Timestamp.from(Instant.now()));