This commit is contained in:
ICKostiantyn.Ivanov
2024-04-14 18:14:42 +02:00
833 changed files with 12280 additions and 3250 deletions
+42
View File
@@ -0,0 +1,42 @@
<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>
<groupId>org.baeldung</groupId>
<artifactId>duckdb</artifactId>
<name>duckdb</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</build>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>persistence-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<duckdb.version>0.10.0</duckdb.version>
</properties>
<dependencies>
<dependency>
<groupId>org.duckdb</groupId>
<artifactId>duckdb_jdbc</artifactId>
<version>${duckdb.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,198 @@
package com.baeldung;
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 java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
class DuckDbAccessIntegrationTest {
private Connection conn = null;
private Statement stmt = null;
@BeforeAll
static void setupOnce() throws Exception {
Class.forName("org.duckdb.DuckDBDriver");
}
@BeforeEach
void setup() throws SQLException {
conn = DriverManager.getConnection("jdbc:duckdb:");
stmt = conn.createStatement();
}
@Test
void whenQueryCurrentDate_thenReturnToday() throws SQLException {
ResultSet rs = stmt.executeQuery("SELECT current_date");
Date currentDate = rs.next() ? rs.getDate(1) : null;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Date expectedDate = calendar.getTime();
assertThat(currentDate).isEqualTo(expectedDate);
}
@Test
void whenReadCsv_thenReturnHeaderAndData() throws SQLException {
String filePath = getResourceAbsolutePath("/customer.csv");
String query = String.format("SELECT * FROM read_csv('%s')", filePath);
ResultSet rs = stmt.executeQuery(query);
ResultSetMetaData metadata = rs.getMetaData();
List<String> actualHeaderNames = new ArrayList<>();
for (int n=1; n<=metadata.getColumnCount(); n++) {
actualHeaderNames.add(metadata.getColumnLabel(n));
}
// Then
List<String> expectedHeaderNames = List.of("CustomerId", "FirstName", "LastName", "Gender");
assertThat(actualHeaderNames).isEqualTo(expectedHeaderNames);
int rowCount = 0;
while (rs.next()) {
rowCount++;
}
assertThat(rowCount).isEqualTo(10);
}
@Test
void whenImportByCsv_thenReturnCorrectRowCount() throws SQLException {
// When
String filePath = getResourceAbsolutePath("/customer.csv");
String query = String.format("CREATE TABLE customer AS SELECT * FROM read_csv('%s')", filePath);
stmt.executeUpdate(query);
// Then
assertThat(getTableRowCount(conn, "customer")).isEqualTo(10);
}
@Test
void whenImportByJson_thenReturnCorrectRowCount() throws SQLException {
// When
String filePath = getResourceAbsolutePath("/product.json");
String query = String.format("CREATE TABLE product AS SELECT * FROM read_json('%s')", filePath);
stmt.executeUpdate(query);
// Then
assertThat(getTableRowCount(conn, "product")).isEqualTo(3);
}
@Test
void whenImportByInsert_thenReturnCorrectRowCount() throws SQLException {
// When
stmt.executeUpdate("CREATE TABLE purchase(customerId BIGINT, productId BIGINT)");
String query = "INSERT INTO purchase(customerId, productId) VALUES (?,?)";
try (PreparedStatement pStmt = conn.prepareStatement(query)) {
pStmt.setInt(1, 101);
pStmt.setInt(2, 1);
pStmt.addBatch();
pStmt.setInt(1, 101);
pStmt.setInt(2, 2);
pStmt.addBatch();
pStmt.setInt(1, 102);
pStmt.setInt(2, 2);
pStmt.addBatch();
pStmt.executeBatch();
}
// Then
assertThat(getTableRowCount(conn, "purchase")).isEqualTo(3);
}
@Test
void whenQueryWithJoin_thenReturnCorrectCount() throws SQLException {
String customerFilePath = getResourceAbsolutePath("/customer.csv");
String productFilePath = getResourceAbsolutePath("/product.json");
whenImportByInsert_thenReturnCorrectRowCount();
String query = String.format("SELECT C.firstName, C.lastName, P.productName " +
"FROM read_csv('%s') AS C, read_json('%s') AS P, purchase S " +
"WHERE S.customerId = C.customerId " +
"AND S.productId = P.productId ",
customerFilePath, productFilePath);
int count = 0;
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
count++;
}
assertThat(count).isEqualTo(3);
}
@Test
void whenExportData_thenFileIsCreated() throws IOException, SQLException {
createPurchaseView(conn);
File tempFile = File.createTempFile("temp", "");
String exportFilePath = tempFile.getAbsolutePath();
String query = String.format("COPY purchase_view TO '%s'", exportFilePath);
stmt.executeUpdate(query);
assertThat(tempFile.length()).isGreaterThan(0);
tempFile.delete();
}
@AfterEach
void tearDown() throws SQLException {
stmt.close();
conn.close();
}
private String getResourceAbsolutePath(String name) {
return this.getClass().getResource(name).getPath().replaceFirst("/", "");
}
private int getTableRowCount(Connection conn, String tableName) throws SQLException {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(String.format("SELECT COUNT(*) FROM %s", tableName));
return (rs.next()) ? rs.getInt(1) : 0;
}
}
private void createPurchaseView(Connection conn) throws SQLException {
whenImportByCsv_thenReturnCorrectRowCount();
whenImportByJson_thenReturnCorrectRowCount();
whenImportByInsert_thenReturnCorrectRowCount();
String query = "CREATE VIEW purchase_view AS " +
"SELECT P.productName, COUNT(*) AS purchaseCount " +
"FROM customer C, product P, purchase S " +
"WHERE S.customerId = C.customerId " +
"AND S.productId = P.productId " +
"GROUP BY P.productName " +
"ORDER BY COUNT(*) DESC ";
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(query);
}
}
}
@@ -0,0 +1,11 @@
CustomerId,FirstName,LastName,Gender
101,John,Smith,Male
102,Sarah,Jones,Female
103,Michael,Johnson,Male
104,Emily,Davis,Female
105,David,Brown,Male
106,Emma,Williams,Female
107,Alexander,Miller,Male
108,Samantha,Anderson,Female
109,Matthew,Taylor,Male
110,Olivia,Thompson,Female
1 CustomerId FirstName LastName Gender
2 101 John Smith Male
3 102 Sarah Jones Female
4 103 Michael Johnson Male
5 104 Emily Davis Female
6 105 David Brown Male
7 106 Emma Williams Female
8 107 Alexander Miller Male
9 108 Samantha Anderson Female
10 109 Matthew Taylor Male
11 110 Olivia Thompson Female
@@ -0,0 +1,17 @@
[
{
"productId": 1,
"productName":"EZ Curl Bar",
"category": "Sports Equipment"
},
{
"productId": 2,
"productName": "7' Barbell",
"category": "Sports Equipment"
},
{
"productId": 3,
"productName": "Single Mouthguard - Black",
"category": "Sports Equipment"
}
]
@@ -0,0 +1,6 @@
## Hibernate Annotations
This module contains articles about Annotations used in Hibernate.
### Relevant Articles:
- [@Subselect Annotation in Hibernate](https://www.baeldung.com/hibernate-subselect)
@@ -0,0 +1,109 @@
<?xml version="1.0"?>
<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>hibernate-annotations-2</artifactId>
<version>0.1-SNAPSHOT</version>
<name>hibernate-annotations-2</name>
<packaging>jar</packaging>
<description>Hibernate annotations module, part 2</description>
<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-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>${org.springframework.data.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate-core.version}</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-testing</artifactId>
<version>${hibernate-core.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>${hibernate-core.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>${tomcat-dbcp.version}</version>
</dependency>
<!-- validation -->
<!-- utils -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.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>io.hypersistence</groupId>
<artifactId>hypersistence-utils-hibernate-60</artifactId>
<version>${hypersistance-utils-hibernate-60.version}</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>${liquibase-core.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<properties>
<!-- Spring -->
<org.springframework.version>6.0.6</org.springframework.version>
<org.springframework.data.version>3.0.3</org.springframework.data.version>
<hibernate-core.version>6.4.2.Final</hibernate-core.version>
<maven.deploy.skip>true</maven.deploy.skip>
<tomcat-dbcp.version>9.0.0.M26</tomcat-dbcp.version>
<hypersistance-utils-hibernate-60.version>3.3.1</hypersistance-utils-hibernate-60.version>
<lombok.version>1.18.30</lombok.version>
<liquibase-core.version>4.24.0</liquibase-core.version>
</properties>
</project>
@@ -0,0 +1,50 @@
package com.baeldung.hibernate;
import com.baeldung.hibernate.subselect.RuntimeConfiguration;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;
public class HibernateAnnotationUtil {
private static final SessionFactory SESSION_FACTORY = buildSessionFactory();
/**
* Utility class
*/
private HibernateAnnotationUtil() {
}
public static SessionFactory getSessionFactory() {
return SESSION_FACTORY;
}
private static SessionFactory buildSessionFactory() {
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(dbSettings())
.build();
Metadata metadata = new MetadataSources(serviceRegistry)
.addAnnotatedClass(RuntimeConfiguration.class)
.buildMetadata();
return metadata.buildSessionFactory();
}
private static Map<String, Object> dbSettings() {
Map<String, Object> dbSettings = new HashMap<>();
dbSettings.put(Environment.URL, "jdbc:h2:mem:spring_hibernate_one_to_many");
dbSettings.put(Environment.USER, "sa");
dbSettings.put(Environment.PASS, "");
dbSettings.put(Environment.DRIVER, "org.h2.Driver");
dbSettings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");
dbSettings.put(Environment.SHOW_SQL, "true");
dbSettings.put(Environment.HBM2DDL_AUTO, "create");
return dbSettings;
}
}
@@ -0,0 +1,67 @@
package com.baeldung.hibernate;
import com.google.common.base.Preconditions;
import java.util.Properties;
import javax.sql.DataSource;
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.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-h2.properties" })
public class PersistenceConfig {
@Autowired
private Environment env;
@Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.baeldung.hibernate" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource dataSource() {
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 PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private final 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", "false");
return hibernateProperties;
}
}
@@ -0,0 +1,43 @@
package com.baeldung.hibernate.subselect;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import java.time.Instant;
import lombok.Data;
import lombok.experimental.Accessors;
import org.hibernate.annotations.Subselect;
@Data
@Accessors(chain = true)
@Entity
// language=sql
@Subselect(value =
"SELECT\n"
+ " ss.id,\n"
+ " ss.attr_key,\n"
+ " ss.val,\n"
+ " ss.created_at\n"
+ " FROM system_settings AS ss\n"
+ " INNER JOIN (\n"
+ " SELECT\n"
+ " ss2.attr_key as k2,\n"
+ " MAX(ss2.created_at) as ca2\n"
+ " FROM system_settings ss2\n"
+ " GROUP BY ss2.attr_key\n"
+ " ) AS t ON t.k2 = ss.attr_key AND t.ca2 = ss.created_at\n"
+ " WHERE ss.type = 'SYSTEM' AND ss.active IS TRUE\n")
public class RuntimeConfiguration {
@Id
private Long id;
@Column(name = "attr_key")
private String key;
@Column(name = "val")
private String value;
@Column(name = "created_at")
private Instant createdAt;
}
@@ -0,0 +1,55 @@
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<changeSet id="4" author="Mikhail Polivakha">
<createTable tableName="system_settings">
<column name="id" type="bigserial" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="attr_key" type="text">
<constraints nullable="false"/>
</column>
<column name="val" type="text">
<constraints nullable="false"/>
</column>
<column name="type" type="text">
<constraints nullable="false"/>
</column>
<column name="active" type="boolean">
<constraints nullable="false"/>
</column>
<column name="created_at" type="timestamptz">
<constraints nullable="false"/>
</column>
</createTable>
<insert tableName="system_settings">
<column name="id">1</column>
<column name="attr_key">splitting.enabled</column>
<column name="val">true</column>
<column name="active">true</column>
<column name="type">SYSTEM</column>
<column name="created_at" valueComputed="NOW()"/>
</insert>
<insert tableName="system_settings">
<column name="id">2</column>
<column name="attr_key">splitting.enabled</column>
<column name="val">false</column>
<column name="active">false</column>
<column name="type">SYSTEM</column>
<column name="created_at" valueComputed="NOW()"/>
</insert>
<insert tableName="system_settings">
<column name="id">3</column>
<column name="attr_key">redelivery.enabled</column>
<column name="val">false</column>
<column name="active">true</column>
<column name="type">ORDER</column>
<column name="created_at" valueComputed="NOW()"/>
</insert>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,7 @@
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<include file="V1__init.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
@@ -0,0 +1,15 @@
# jdbc.X
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jdbc.eventGeneratedId=sa
jdbc.user=sa
jdbc.pass=
# hibernate.X
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
@@ -0,0 +1,18 @@
package com.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import com.baeldung.hibernate.PersistenceConfig;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}
@@ -0,0 +1,65 @@
package com.baeldung.hibernate.subselect;
import com.baeldung.hibernate.HibernateAnnotationUtil;
import jakarta.persistence.criteria.Root;
import liquibase.Contexts;
import liquibase.LabelExpression;
import liquibase.Liquibase;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.resource.ClassLoaderResourceAccessor;
import org.hibernate.Session;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class SubselectIntegrationTest {
@BeforeAll
static void setUp() {
Session currentSession = HibernateAnnotationUtil.getSessionFactory().getCurrentSession();
currentSession.beginTransaction();
currentSession.doWork(it -> {
Liquibase liquibase;
try {
liquibase = new Liquibase(
"migrations/master.xml",
new ClassLoaderResourceAccessor(),
DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(it))
);
liquibase.update(new Contexts(), new LabelExpression(),true);
} catch (LiquibaseException e) {
throw new RuntimeException(e);
}
});
currentSession.getTransaction().commit();
}
@Test
void givenEntityMarkedWithSubselect_whenSelectingRuntimeConfigByKey_thenSelectedSuccessfully() {
String key = "splitting.enabled";
Session entityManager = HibernateAnnotationUtil.getSessionFactory().getCurrentSession();
entityManager.beginTransaction();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<RuntimeConfiguration> query = criteriaBuilder.createQuery(RuntimeConfiguration.class);
Root<RuntimeConfiguration> root = query.from(RuntimeConfiguration.class);
RuntimeConfiguration configurationParameter = entityManager.createQuery(
query.select(root).where(criteriaBuilder.equal(root.get("key"), key))
).getSingleResult();
entityManager.getTransaction().commit();
Assertions.assertThat(configurationParameter.getValue()).isEqualTo("true");
}
}
@@ -13,3 +13,4 @@ This module contains articles about Annotations used in Hibernate.
- [Hibernate @CreationTimestamp and @UpdateTimestamp](https://www.baeldung.com/hibernate-creationtimestamp-updatetimestamp)
- [Difference Between @JoinColumn and @PrimaryKeyJoinColumn in JPA](https://www.baeldung.com/java-jpa-join-vs-primarykeyjoin)
- [A Guide to the @SoftDelete Annotation in Hibernate](https://www.baeldung.com/java-hibernate-softdelete-annotation)
- [@Subselect Annotation in Hibernate](https://www.baeldung.com/hibernate-subselect)
@@ -81,6 +81,16 @@
<artifactId>hypersistence-utils-hibernate-60</artifactId>
<version>${hypersistance-utils-hibernate-60.version}</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>${liquibase-core.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
<properties>
@@ -91,6 +101,8 @@
<maven.deploy.skip>true</maven.deploy.skip>
<tomcat-dbcp.version>9.0.0.M26</tomcat-dbcp.version>
<hypersistance-utils-hibernate-60.version>3.3.1</hypersistance-utils-hibernate-60.version>
<lombok.version>1.18.30</lombok.version>
<liquibase-core.version>4.24.0</liquibase-core.version>
</properties>
</project>
+2 -1
View File
@@ -13,4 +13,5 @@ This module contains articles specific to use of Hibernate as a JPA implementati
- [Enabling Transaction Locks in Spring Data JPA](https://www.baeldung.com/java-jpa-transaction-locks)
- [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context)
- [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference)
- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable)
- [JPA Entities and the Serializable Interface](https://www.baeldung.com/jpa-entities-serializable)
- [The @Struct Annotation Type in Hibernate – Structured User-Defined Types](https://www.baeldung.com/java-hibernate-struct-annotation)
@@ -0,0 +1,51 @@
package com.baeldung.hibernate.struct.entities;
import jakarta.persistence.*;
@Entity
public class StructDepartment {
@Id
@GeneratedValue
private Integer id;
@Column
private String departmentName;
@Embedded
@Column
private StructManager manager;
@Override
public String toString() {
return "Department{" +
"id=" + id +
", departmentName='" + departmentName + '\'' +
", manager=" + manager +
'}';
}
public StructDepartment(String departmentName, StructManager manager) {
this.departmentName = departmentName;
this.manager = manager;
}
public Integer getId() {
return id;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public StructManager getManager() {
return manager;
}
public void setManager(StructManager manager) {
this.manager = manager;
}
}
@@ -0,0 +1,52 @@
package com.baeldung.hibernate.struct.entities;
import jakarta.persistence.Embeddable;
import org.hibernate.annotations.Struct;
import java.io.Serializable;
@Embeddable
@Struct(name = "Department_Manager_Type", attributes = {"firstName", "lastName", "qualification"})
public class StructManager implements Serializable {
private String firstName;
private String lastName;
private String qualification;
@Override
public String toString() {
return "Manager{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", qualification='" + qualification + '\'' +
'}';
}
public StructManager(String firstName, String lastName, String qualification) {
this.firstName = firstName;
this.lastName = lastName;
this.qualification = qualification;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getQualification() {
return qualification;
}
public void setQualification(String qualification) {
this.qualification = qualification;
}
}
@@ -0,0 +1,101 @@
package com.baeldung.hibernate.struct;
import com.baeldung.hibernate.struct.entities.StructDepartment;
import com.baeldung.hibernate.struct.entities.StructManager;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
public class HibernateStructUnitTest {
private Session session;
private Transaction transaction;
public static SessionFactory getSessionFactoryByProperties(Properties properties) throws IOException {
ServiceRegistry serviceRegistry = configureServiceRegistry(properties);
return makeSessionFactory(serviceRegistry);
}
private static SessionFactory makeSessionFactory(ServiceRegistry serviceRegistry) {
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
metadataSources.addPackage("com.baeldung.hibernate.struct.entities");
metadataSources.addAnnotatedClass(StructDepartment.class);
metadataSources.addAnnotatedClass(StructManager.class);
Metadata metadata = metadataSources.getMetadataBuilder()
.build();
return metadata.getSessionFactoryBuilder()
.build();
}
private static ServiceRegistry configureServiceRegistry(Properties properties) throws IOException {
return new StandardServiceRegistryBuilder().applySettings(properties)
.build();
}
public static Properties getProperties() throws IOException {
Properties properties = new Properties();
URL propertiesURL = Thread.currentThread()
.getContextClassLoader()
.getResource(StringUtils.defaultString(PROPERTY_FILE_NAME, "hibernate-derby.properties"));
try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) {
properties.load(inputStream);
}
return properties;
}
private static ServiceRegistry configureServiceRegistry() throws IOException {
return configureServiceRegistry(getProperties());
}
private static String PROPERTY_FILE_NAME;
public static SessionFactory getSessionFactory(String propertyFileName) throws IOException {
PROPERTY_FILE_NAME = propertyFileName;
ServiceRegistry serviceRegistry = configureServiceRegistry();
return makeSessionFactory(serviceRegistry);
}
@Before
public void setUp() throws IOException {
session = getSessionFactory("hibernate-derby.properties")
.openSession();
transaction = session.beginTransaction();
transaction.commit();
transaction = session.beginTransaction();
}
@After
public void tearDown() {
transaction.rollback();
session.close();
}
/* This unit test is for reference only because the Hibernate dialect for
Apache Derby database does not support @Struct annotation.
@Test
public void givenSaveDepartmentObject_ThenManagerUDTExists() {
StructDepartment d = new StructDepartment("Information Technology"
, new StructManager("Zeeshan", "Arif", "Qualified"));
session.persist(d);
session.flush();
session.clear();
}*/
}
@@ -0,0 +1,17 @@
hibernate.connection.driver_class=org.apache.derby.jdbc.EmbeddedDriver
hibernate.connection.url=jdbc:derby:db/derby.dbfile;create=true
hibernate.connection.username=
hibernate.connection.autocommit=true
jdbc.password=
hibernate.dialect=org.hibernate.dialect.DerbyDialect
# enable to see Hibernate generated SQL
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.acquire_increment=5
hibernate.c3p0.timeout=1800
@@ -13,3 +13,4 @@ This module contains articles about use of Queries in Hibernate.
- [Distinct Queries in HQL](https://www.baeldung.com/java-hql-distinct)
- [JPA and Hibernate – Criteria vs. JPQL vs. HQL Query](https://www.baeldung.com/jpql-hql-criteria-query)
- [Database Keywords as Columns in Hibernate Entities](https://www.baeldung.com/java-hibernate-db-keywords-as-columns)
- [Get List of Entity From Database in Hibernate](https://www.baeldung.com/java-hibernate-fetch-entity-list)
@@ -0,0 +1,40 @@
package com.baeldung.hibernate.listentity.entity;
import java.util.List;
import jakarta.persistence.*;
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "department", fetch = FetchType.EAGER)
private List<Employee> employees;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
@@ -0,0 +1,41 @@
package com.baeldung.hibernate.listentity.entity;
import jakarta.persistence.*;
@Entity
@NamedQuery(name = "findAllEmployees", query = "SELECT e FROM Employee e")
@NamedQuery(name = "findEmployeesByDepartment", query = "SELECT e FROM Employee e WHERE e.department = :department ORDER BY e.lastName ASC")
public class Employee {
@Id
@GeneratedValue
private Long id;
private String lastName;
private String department;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
@@ -0,0 +1,88 @@
package com.baeldung.hibernate.listentity.service;
import java.util.Collections;
import java.util.List;
import jakarta.persistence.*;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.springframework.stereotype.Service;
import com.baeldung.hibernate.listentity.entity.Department;
import com.baeldung.hibernate.listentity.entity.Employee;
@Service
public class EmployeeService {
@PersistenceContext
private EntityManager entityManager;
public List<Employee> getAllEmployeesUsingJPQL() {
String jpqlQuery = "SELECT e FROM Employee e";
Query query = entityManager.createQuery(jpqlQuery, Employee.class);
return query.getResultList();
}
public List<Employee> getAllEmployeesByDepartmentUsingJPQL() {
String jpqlQuery = "SELECT e FROM Employee e WHERE e.department = 'Engineering' ORDER BY e.lastName ASC";
Query query = entityManager.createQuery(jpqlQuery, Employee.class);
return query.getResultList();
}
public List<Employee> getAllEmployeesUsingNamedQuery() {
Query query = entityManager.createNamedQuery("findAllEmployees", Employee.class);
return query.getResultList();
}
public List<Employee> getAllEmployeesByDepartmentUsingNamedQuery(String department) {
Query query = entityManager.createNamedQuery("findEmployeesByDepartment", Employee.class);
query.setParameter("department", department);
return query.getResultList();
}
public List<Employee> getAllEmployeesUsingCriteriaAPI() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> employeeRoot = criteriaQuery.from(Employee.class);
criteriaQuery.select(employeeRoot);
Query query = entityManager.createQuery(criteriaQuery);
return query.getResultList();
}
public List<Employee> getAllEmployeesByDepartmentUsingCriteriaAPI(String department) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> employeeRoot = criteriaQuery.from(Employee.class);
Predicate departmentPredicate = criteriaBuilder.equal(employeeRoot.get("department"), department);
Path<Object> sortByPath = employeeRoot.get("lastName");
criteriaQuery.orderBy(criteriaBuilder.asc(sortByPath));
criteriaQuery.select(employeeRoot)
.where(departmentPredicate);
Query query = entityManager.createQuery(criteriaQuery);
return query.getResultList();
}
public List<Employee> getAllEmployeesByDepartmentUsingOneToManyAnnotations(String departmentName) {
try {
// Retrieve the department by its name
Department department = entityManager.createQuery("SELECT d FROM Department d WHERE d.name = :name", Department.class)
.setParameter("name", departmentName)
.getSingleResult();
// Return the list of employees associated with the department
return department.getEmployees();
} catch (NoResultException e) {
return Collections.emptyList();
}
}
}
@@ -0,0 +1,56 @@
/*
* This file is generated by jOOQ.
*/
package com.baeldung.jooq.jointables;
import com.baeldung.jooq.jointables.public_.Public;
import java.util.Arrays;
import java.util.List;
import org.jooq.Constants;
import org.jooq.Schema;
import org.jooq.impl.CatalogImpl;
/**
* This class is generated by jOOQ.
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
public class DefaultCatalog extends CatalogImpl {
private static final long serialVersionUID = 1L;
/**
* The reference instance of <code>DEFAULT_CATALOG</code>
*/
public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog();
/**
* The schema <code>public</code>.
*/
public final Public PUBLIC = Public.PUBLIC;
/**
* No further instances allowed
*/
private DefaultCatalog() {
super("");
}
@Override
public final List<Schema> getSchemas() {
return Arrays.asList(
Public.PUBLIC
);
}
/**
* A reference to the 3.19 minor release of the code generator. If this
* doesn't compile, it's because the runtime library uses an older minor
* release, namely: 3.19. You can turn off the generation of this reference
* by specifying /configuration/generator/generate/jooqVersionReference
*/
private static final String REQUIRE_RUNTIME_JOOQ_VERSION = Constants.VERSION_3_19;
}
@@ -0,0 +1,75 @@
package com.baeldung.jooq.jointables;
import static org.jooq.impl.DSL.field;
import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SelectJoinStep;
import com.baeldung.jooq.jointables.public_.Tables;
public class JoinTables {
public static Result<Record> usingJoinMethod(DSLContext context) {
SelectJoinStep<Record> query = context.select()
.from(Tables.BOOK)
.join(Tables.BOOKAUTHOR)
.on(field(Tables.BOOK.AUTHOR_ID).eq(field(Tables.BOOKAUTHOR.ID)));
return query.fetch();
}
public static Result<Record> usingMultipleJoinMethod(DSLContext context) {
SelectJoinStep<Record> query = context.select()
.from(Tables.BOOK)
.join(Tables.BOOKAUTHOR)
.on(field(Tables.BOOK.AUTHOR_ID).eq(field(Tables.BOOKAUTHOR.ID)))
.join(Tables.STORE)
.on(field(Tables.BOOK.STORE_ID).eq(field(Tables.STORE.ID)));
return query.fetch();
}
public static Result<Record> usingLeftOuterJoinMethod(DSLContext context) {
SelectJoinStep<Record> query = context.select()
.from(Tables.BOOK)
.leftOuterJoin(Tables.BOOKAUTHOR)
.on(field(Tables.BOOK.AUTHOR_ID).eq(field(Tables.BOOKAUTHOR.ID)));
return query.fetch();
}
public static Result<Record> usingRightOuterJoinMethod(DSLContext context) {
SelectJoinStep<Record> query = context.select()
.from(Tables.BOOK)
.rightOuterJoin(Tables.BOOKAUTHOR)
.on(field(Tables.BOOK.AUTHOR_ID).eq(field(Tables.BOOKAUTHOR.ID)));
return query.fetch();
}
public static Result<Record> usingFullOuterJoinMethod(DSLContext context) {
SelectJoinStep<Record> query = context.select()
.from(Tables.BOOK)
.fullOuterJoin(Tables.BOOKAUTHOR)
.on(field(Tables.BOOK.AUTHOR_ID).eq(field(Tables.BOOKAUTHOR.ID)));
return query.fetch();
}
public static Result<Record> usingNaturalJoinMethod(DSLContext context) {
SelectJoinStep<Record> query = context.select()
.from(Tables.BOOK)
.naturalJoin(Tables.BOOKAUTHOR);
return query.fetch();
}
public static Result<Record> usingCrossJoinMethod(DSLContext context) {
SelectJoinStep<Record> query = context.select()
.from(Tables.STORE)
.crossJoin(Tables.BOOK);
return query.fetch();
}
public static void printResult(Result<Record> result) {
for (Record record : result) {
System.out.println(record);
}
}
}
@@ -0,0 +1,34 @@
/*
* This file is generated by jOOQ.
*/
package com.baeldung.jooq.jointables.public_;
import com.baeldung.jooq.jointables.public_.tables.Book;
import com.baeldung.jooq.jointables.public_.tables.Bookauthor;
import com.baeldung.jooq.jointables.public_.tables.Store;
import com.baeldung.jooq.jointables.public_.tables.records.BookRecord;
import com.baeldung.jooq.jointables.public_.tables.records.BookauthorRecord;
import com.baeldung.jooq.jointables.public_.tables.records.StoreRecord;
import org.jooq.TableField;
import org.jooq.UniqueKey;
import org.jooq.impl.DSL;
import org.jooq.impl.Internal;
/**
* A class modelling foreign key relationships and constraints of tables in
* public.
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
public class Keys {
// -------------------------------------------------------------------------
// UNIQUE and PRIMARY KEY definitions
// -------------------------------------------------------------------------
public static final UniqueKey<BookRecord> BOOK_PKEY = Internal.createUniqueKey(Book.BOOK, DSL.name("Book_pkey"), new TableField[] { Book.BOOK.ID }, true);
public static final UniqueKey<BookauthorRecord> AUTHOR_PKEY = Internal.createUniqueKey(Bookauthor.BOOKAUTHOR, DSL.name("Author_pkey"), new TableField[] { Bookauthor.BOOKAUTHOR.ID }, true);
public static final UniqueKey<StoreRecord> STORE_PKEY = Internal.createUniqueKey(Store.STORE, DSL.name("Store_pkey"), new TableField[] { Store.STORE.ID }, true);
}
@@ -0,0 +1,69 @@
/*
* This file is generated by jOOQ.
*/
package com.baeldung.jooq.jointables.public_;
import com.baeldung.jooq.jointables.DefaultCatalog;
import com.baeldung.jooq.jointables.public_.tables.Book;
import com.baeldung.jooq.jointables.public_.tables.Bookauthor;
import com.baeldung.jooq.jointables.public_.tables.Store;
import java.util.Arrays;
import java.util.List;
import org.jooq.Catalog;
import org.jooq.Table;
import org.jooq.impl.SchemaImpl;
/**
* This class is generated by jOOQ.
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
public class Public extends SchemaImpl {
private static final long serialVersionUID = 1L;
/**
* The reference instance of <code>public</code>
*/
public static final Public PUBLIC = new Public();
/**
* The table <code>public.Book</code>.
*/
public final Book BOOK = Book.BOOK;
/**
* The table <code>public.BookAuthor</code>.
*/
public final Bookauthor BOOKAUTHOR = Bookauthor.BOOKAUTHOR;
/**
* The table <code>public.Store</code>.
*/
public final Store STORE = Store.STORE;
/**
* No further instances allowed
*/
private Public() {
super("public", null);
}
@Override
public Catalog getCatalog() {
return DefaultCatalog.DEFAULT_CATALOG;
}
@Override
public final List<Table<?>> getTables() {
return Arrays.asList(
Book.BOOK,
Bookauthor.BOOKAUTHOR,
Store.STORE
);
}
}
@@ -0,0 +1,32 @@
/*
* This file is generated by jOOQ.
*/
package com.baeldung.jooq.jointables.public_;
import com.baeldung.jooq.jointables.public_.tables.Book;
import com.baeldung.jooq.jointables.public_.tables.Bookauthor;
import com.baeldung.jooq.jointables.public_.tables.Store;
/**
* Convenience access to all tables in public.
*/
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
public class Tables {
/**
* The table <code>public.Book</code>.
*/
public static final Book BOOK = Book.BOOK;
/**
* The table <code>public.BookAuthor</code>.
*/
public static final Bookauthor BOOKAUTHOR = Bookauthor.BOOKAUTHOR;
/**
* The table <code>public.Store</code>.
*/
public static final Store STORE = Store.STORE;
}

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