Merge branch 'master' of https://github.com/sIvanovKonstantyn/tutorials
This commit is contained in:
@@ -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
|
||||
|
@@ -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>
|
||||
+50
@@ -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;
|
||||
}
|
||||
}
|
||||
+67
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -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;
|
||||
}
|
||||
+55
@@ -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>
|
||||
+15
@@ -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
|
||||
|
||||
+18
@@ -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() {
|
||||
}
|
||||
}
|
||||
+65
@@ -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>
|
||||
@@ -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)
|
||||
|
||||
+51
@@ -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;
|
||||
}
|
||||
}
|
||||
+52
@@ -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;
|
||||
}
|
||||
}
|
||||
+101
@@ -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)
|
||||
|
||||
+40
@@ -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;
|
||||
}
|
||||
}
|
||||
+41
@@ -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;
|
||||
}
|
||||
}
|
||||
+88
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -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);
|
||||
}
|
||||
+69
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
+32
@@ -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;
|
||||
}
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package com.baeldung.jooq.jointables.public_.tables;
|
||||
|
||||
|
||||
import com.baeldung.jooq.jointables.public_.Keys;
|
||||
import com.baeldung.jooq.jointables.public_.Public;
|
||||
import com.baeldung.jooq.jointables.public_.tables.records.BookRecord;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.PlainSQL;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.SQL;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Stringly;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.TableOptions;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.SQLDataType;
|
||||
import org.jooq.impl.TableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public class Book extends TableImpl<BookRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>public.Book</code>
|
||||
*/
|
||||
public static final Book BOOK = new Book();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public Class<BookRecord> getRecordType() {
|
||||
return BookRecord.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>public.Book.id</code>.
|
||||
*/
|
||||
public final TableField<BookRecord, Integer> ID = createField(DSL.name("id"), SQLDataType.INTEGER.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>public.Book.author_id</code>.
|
||||
*/
|
||||
public final TableField<BookRecord, Integer> AUTHOR_ID = createField(DSL.name("author_id"), SQLDataType.INTEGER, this, "");
|
||||
|
||||
/**
|
||||
* The column <code>public.Book.title</code>.
|
||||
*/
|
||||
public final TableField<BookRecord, String> TITLE = createField(DSL.name("title"), SQLDataType.VARCHAR, this, "");
|
||||
|
||||
/**
|
||||
* The column <code>public.Book.description</code>.
|
||||
*/
|
||||
public final TableField<BookRecord, String> DESCRIPTION = createField(DSL.name("description"), SQLDataType.VARCHAR, this, "");
|
||||
|
||||
/**
|
||||
* The column <code>public.Book.store_id</code>.
|
||||
*/
|
||||
public final TableField<BookRecord, Integer> STORE_ID = createField(DSL.name("store_id"), SQLDataType.INTEGER, this, "");
|
||||
|
||||
private Book(Name alias, Table<BookRecord> aliased) {
|
||||
this(alias, aliased, (Field<?>[]) null, null);
|
||||
}
|
||||
|
||||
private Book(Name alias, Table<BookRecord> aliased, Field<?>[] parameters, Condition where) {
|
||||
super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table(), where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>public.Book</code> table reference
|
||||
*/
|
||||
public Book(String alias) {
|
||||
this(DSL.name(alias), BOOK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>public.Book</code> table reference
|
||||
*/
|
||||
public Book(Name alias) {
|
||||
this(alias, BOOK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <code>public.Book</code> table reference
|
||||
*/
|
||||
public Book() {
|
||||
this(DSL.name("Book"), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Schema getSchema() {
|
||||
return aliased() ? null : Public.PUBLIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniqueKey<BookRecord> getPrimaryKey() {
|
||||
return Keys.BOOK_PKEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Book as(String alias) {
|
||||
return new Book(DSL.name(alias), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Book as(Name alias) {
|
||||
return new Book(alias, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Book as(Table<?> alias) {
|
||||
return new Book(alias.getQualifiedName(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Book rename(String name) {
|
||||
return new Book(DSL.name(name), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Book rename(Name name) {
|
||||
return new Book(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Book rename(Table<?> name) {
|
||||
return new Book(name.getQualifiedName(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Book where(Condition condition) {
|
||||
return new Book(getQualifiedName(), aliased() ? this : null, null, condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Book where(Collection<? extends Condition> conditions) {
|
||||
return where(DSL.and(conditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Book where(Condition... conditions) {
|
||||
return where(DSL.and(conditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Book where(Field<Boolean> condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Book where(SQL condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Book where(@Stringly.SQL String condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Book where(@Stringly.SQL String condition, Object... binds) {
|
||||
return where(DSL.condition(condition, binds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Book where(@Stringly.SQL String condition, QueryPart... parts) {
|
||||
return where(DSL.condition(condition, parts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Book whereExists(Select<?> select) {
|
||||
return where(DSL.exists(select));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Book whereNotExists(Select<?> select) {
|
||||
return where(DSL.notExists(select));
|
||||
}
|
||||
}
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package com.baeldung.jooq.jointables.public_.tables;
|
||||
|
||||
|
||||
import com.baeldung.jooq.jointables.public_.Keys;
|
||||
import com.baeldung.jooq.jointables.public_.Public;
|
||||
import com.baeldung.jooq.jointables.public_.tables.records.BookauthorRecord;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.PlainSQL;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.SQL;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Stringly;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.TableOptions;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.SQLDataType;
|
||||
import org.jooq.impl.TableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public class Bookauthor extends TableImpl<BookauthorRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>public.BookAuthor</code>
|
||||
*/
|
||||
public static final Bookauthor BOOKAUTHOR = new Bookauthor();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public Class<BookauthorRecord> getRecordType() {
|
||||
return BookauthorRecord.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>public.BookAuthor.id</code>.
|
||||
*/
|
||||
public final TableField<BookauthorRecord, Integer> ID = createField(DSL.name("id"), SQLDataType.INTEGER.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>public.BookAuthor.name</code>.
|
||||
*/
|
||||
public final TableField<BookauthorRecord, String> NAME = createField(DSL.name("name"), SQLDataType.VARCHAR.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>public.BookAuthor.country</code>.
|
||||
*/
|
||||
public final TableField<BookauthorRecord, String> COUNTRY = createField(DSL.name("country"), SQLDataType.VARCHAR, this, "");
|
||||
|
||||
private Bookauthor(Name alias, Table<BookauthorRecord> aliased) {
|
||||
this(alias, aliased, (Field<?>[]) null, null);
|
||||
}
|
||||
|
||||
private Bookauthor(Name alias, Table<BookauthorRecord> aliased, Field<?>[] parameters, Condition where) {
|
||||
super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table(), where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>public.BookAuthor</code> table reference
|
||||
*/
|
||||
public Bookauthor(String alias) {
|
||||
this(DSL.name(alias), BOOKAUTHOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>public.BookAuthor</code> table reference
|
||||
*/
|
||||
public Bookauthor(Name alias) {
|
||||
this(alias, BOOKAUTHOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <code>public.BookAuthor</code> table reference
|
||||
*/
|
||||
public Bookauthor() {
|
||||
this(DSL.name("BookAuthor"), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Schema getSchema() {
|
||||
return aliased() ? null : Public.PUBLIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniqueKey<BookauthorRecord> getPrimaryKey() {
|
||||
return Keys.AUTHOR_PKEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bookauthor as(String alias) {
|
||||
return new Bookauthor(DSL.name(alias), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bookauthor as(Name alias) {
|
||||
return new Bookauthor(alias, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bookauthor as(Table<?> alias) {
|
||||
return new Bookauthor(alias.getQualifiedName(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor rename(String name) {
|
||||
return new Bookauthor(DSL.name(name), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor rename(Name name) {
|
||||
return new Bookauthor(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor rename(Table<?> name) {
|
||||
return new Bookauthor(name.getQualifiedName(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor where(Condition condition) {
|
||||
return new Bookauthor(getQualifiedName(), aliased() ? this : null, null, condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor where(Collection<? extends Condition> conditions) {
|
||||
return where(DSL.and(conditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor where(Condition... conditions) {
|
||||
return where(DSL.and(conditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor where(Field<Boolean> condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Bookauthor where(SQL condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Bookauthor where(@Stringly.SQL String condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Bookauthor where(@Stringly.SQL String condition, Object... binds) {
|
||||
return where(DSL.condition(condition, binds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Bookauthor where(@Stringly.SQL String condition, QueryPart... parts) {
|
||||
return where(DSL.condition(condition, parts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor whereExists(Select<?> select) {
|
||||
return where(DSL.exists(select));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Bookauthor whereNotExists(Select<?> select) {
|
||||
return where(DSL.notExists(select));
|
||||
}
|
||||
}
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package com.baeldung.jooq.jointables.public_.tables;
|
||||
|
||||
|
||||
import com.baeldung.jooq.jointables.public_.Keys;
|
||||
import com.baeldung.jooq.jointables.public_.Public;
|
||||
import com.baeldung.jooq.jointables.public_.tables.records.StoreRecord;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jooq.Condition;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.PlainSQL;
|
||||
import org.jooq.QueryPart;
|
||||
import org.jooq.SQL;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Stringly;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.TableOptions;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.jooq.impl.SQLDataType;
|
||||
import org.jooq.impl.TableImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public class Store extends TableImpl<StoreRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The reference instance of <code>public.Store</code>
|
||||
*/
|
||||
public static final Store STORE = new Store();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public Class<StoreRecord> getRecordType() {
|
||||
return StoreRecord.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>public.Store.id</code>.
|
||||
*/
|
||||
public final TableField<StoreRecord, Integer> ID = createField(DSL.name("id"), SQLDataType.INTEGER.nullable(false), this, "");
|
||||
|
||||
/**
|
||||
* The column <code>public.Store.name</code>.
|
||||
*/
|
||||
public final TableField<StoreRecord, String> NAME = createField(DSL.name("name"), SQLDataType.VARCHAR.nullable(false), this, "");
|
||||
|
||||
private Store(Name alias, Table<StoreRecord> aliased) {
|
||||
this(alias, aliased, (Field<?>[]) null, null);
|
||||
}
|
||||
|
||||
private Store(Name alias, Table<StoreRecord> aliased, Field<?>[] parameters, Condition where) {
|
||||
super(alias, null, aliased, parameters, DSL.comment(""), TableOptions.table(), where);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>public.Store</code> table reference
|
||||
*/
|
||||
public Store(String alias) {
|
||||
this(DSL.name(alias), STORE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an aliased <code>public.Store</code> table reference
|
||||
*/
|
||||
public Store(Name alias) {
|
||||
this(alias, STORE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a <code>public.Store</code> table reference
|
||||
*/
|
||||
public Store() {
|
||||
this(DSL.name("Store"), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Schema getSchema() {
|
||||
return aliased() ? null : Public.PUBLIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UniqueKey<StoreRecord> getPrimaryKey() {
|
||||
return Keys.STORE_PKEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Store as(String alias) {
|
||||
return new Store(DSL.name(alias), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Store as(Name alias) {
|
||||
return new Store(alias, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Store as(Table<?> alias) {
|
||||
return new Store(alias.getQualifiedName(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Store rename(String name) {
|
||||
return new Store(DSL.name(name), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Store rename(Name name) {
|
||||
return new Store(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename this table
|
||||
*/
|
||||
@Override
|
||||
public Store rename(Table<?> name) {
|
||||
return new Store(name.getQualifiedName(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Store where(Condition condition) {
|
||||
return new Store(getQualifiedName(), aliased() ? this : null, null, condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Store where(Collection<? extends Condition> conditions) {
|
||||
return where(DSL.and(conditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Store where(Condition... conditions) {
|
||||
return where(DSL.and(conditions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Store where(Field<Boolean> condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Store where(SQL condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Store where(@Stringly.SQL String condition) {
|
||||
return where(DSL.condition(condition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Store where(@Stringly.SQL String condition, Object... binds) {
|
||||
return where(DSL.condition(condition, binds));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
@PlainSQL
|
||||
public Store where(@Stringly.SQL String condition, QueryPart... parts) {
|
||||
return where(DSL.condition(condition, parts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Store whereExists(Select<?> select) {
|
||||
return where(DSL.exists(select));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an inline derived table from this table
|
||||
*/
|
||||
@Override
|
||||
public Store whereNotExists(Select<?> select) {
|
||||
return where(DSL.notExists(select));
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package com.baeldung.jooq.jointables.public_.tables.records;
|
||||
|
||||
|
||||
import com.baeldung.jooq.jointables.public_.tables.Book;
|
||||
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.impl.UpdatableRecordImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public class BookRecord extends UpdatableRecordImpl<BookRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Setter for <code>public.Book.id</code>.
|
||||
*/
|
||||
public void setId(Integer value) {
|
||||
set(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.Book.id</code>.
|
||||
*/
|
||||
public Integer getId() {
|
||||
return (Integer) get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>public.Book.author_id</code>.
|
||||
*/
|
||||
public void setAuthorId(Integer value) {
|
||||
set(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.Book.author_id</code>.
|
||||
*/
|
||||
public Integer getAuthorId() {
|
||||
return (Integer) get(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>public.Book.title</code>.
|
||||
*/
|
||||
public void setTitle(String value) {
|
||||
set(2, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.Book.title</code>.
|
||||
*/
|
||||
public String getTitle() {
|
||||
return (String) get(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>public.Book.description</code>.
|
||||
*/
|
||||
public void setDescription(String value) {
|
||||
set(3, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.Book.description</code>.
|
||||
*/
|
||||
public String getDescription() {
|
||||
return (String) get(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>public.Book.store_id</code>.
|
||||
*/
|
||||
public void setStoreId(Integer value) {
|
||||
set(4, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.Book.store_id</code>.
|
||||
*/
|
||||
public Integer getStoreId() {
|
||||
return (Integer) get(4);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary key information
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Record1<Integer> key() {
|
||||
return (Record1) super.key();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a detached BookRecord
|
||||
*/
|
||||
public BookRecord() {
|
||||
super(Book.BOOK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a detached, initialised BookRecord
|
||||
*/
|
||||
public BookRecord(Integer id, Integer authorId, String title, String description, Integer storeId) {
|
||||
super(Book.BOOK);
|
||||
|
||||
setId(id);
|
||||
setAuthorId(authorId);
|
||||
setTitle(title);
|
||||
setDescription(description);
|
||||
setStoreId(storeId);
|
||||
resetChangedOnNotNull();
|
||||
}
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package com.baeldung.jooq.jointables.public_.tables.records;
|
||||
|
||||
|
||||
import com.baeldung.jooq.jointables.public_.tables.Bookauthor;
|
||||
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.impl.UpdatableRecordImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public class BookauthorRecord extends UpdatableRecordImpl<BookauthorRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Setter for <code>public.BookAuthor.id</code>.
|
||||
*/
|
||||
public void setId(Integer value) {
|
||||
set(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.BookAuthor.id</code>.
|
||||
*/
|
||||
public Integer getId() {
|
||||
return (Integer) get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>public.BookAuthor.name</code>.
|
||||
*/
|
||||
public void setName(String value) {
|
||||
set(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.BookAuthor.name</code>.
|
||||
*/
|
||||
public String getName() {
|
||||
return (String) get(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>public.BookAuthor.country</code>.
|
||||
*/
|
||||
public void setCountry(String value) {
|
||||
set(2, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.BookAuthor.country</code>.
|
||||
*/
|
||||
public String getCountry() {
|
||||
return (String) get(2);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary key information
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Record1<Integer> key() {
|
||||
return (Record1) super.key();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a detached BookauthorRecord
|
||||
*/
|
||||
public BookauthorRecord() {
|
||||
super(Bookauthor.BOOKAUTHOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a detached, initialised BookauthorRecord
|
||||
*/
|
||||
public BookauthorRecord(Integer id, String name, String country) {
|
||||
super(Bookauthor.BOOKAUTHOR);
|
||||
|
||||
setId(id);
|
||||
setName(name);
|
||||
setCountry(country);
|
||||
resetChangedOnNotNull();
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is generated by jOOQ.
|
||||
*/
|
||||
package com.baeldung.jooq.jointables.public_.tables.records;
|
||||
|
||||
|
||||
import com.baeldung.jooq.jointables.public_.tables.Store;
|
||||
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.impl.UpdatableRecordImpl;
|
||||
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@SuppressWarnings({ "all", "unchecked", "rawtypes", "this-escape" })
|
||||
public class StoreRecord extends UpdatableRecordImpl<StoreRecord> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Setter for <code>public.Store.id</code>.
|
||||
*/
|
||||
public void setId(Integer value) {
|
||||
set(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.Store.id</code>.
|
||||
*/
|
||||
public Integer getId() {
|
||||
return (Integer) get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for <code>public.Store.name</code>.
|
||||
*/
|
||||
public void setName(String value) {
|
||||
set(1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for <code>public.Store.name</code>.
|
||||
*/
|
||||
public String getName() {
|
||||
return (String) get(1);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary key information
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public Record1<Integer> key() {
|
||||
return (Record1) super.key();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a detached StoreRecord
|
||||
*/
|
||||
public StoreRecord() {
|
||||
super(Store.STORE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a detached, initialised StoreRecord
|
||||
*/
|
||||
public StoreRecord(Integer id, String name) {
|
||||
super(Store.STORE);
|
||||
|
||||
setId(id);
|
||||
setName(name);
|
||||
resetChangedOnNotNull();
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package com.baeldung.jooq.jointables;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.jooq.jointables.public_.Tables;
|
||||
import com.baeldung.jooq.jointables.public_.tables.Book;
|
||||
import com.baeldung.jooq.jointables.public_.tables.Bookauthor;
|
||||
import com.baeldung.jooq.jointables.public_.tables.Store;
|
||||
|
||||
public class JoinTablesLiveTest {
|
||||
|
||||
static DSLContext context;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
// URL jooqConfigURL = getClass().getClassLoader().getResource("jooq-config-2.xml");
|
||||
// File file = new File(jooqConfigURL.getFile());
|
||||
// GenerationTool.generate(Files.readString(file.toPath()));
|
||||
|
||||
String url = "jdbc:postgresql://localhost:5432/postgres";
|
||||
String username = "postgres";
|
||||
String password = "";
|
||||
|
||||
Connection conn = DriverManager.getConnection(url, username, password);
|
||||
context = DSL.using(conn, SQLDialect.POSTGRES);
|
||||
|
||||
context.insertInto(Tables.STORE, Store.STORE.ID, Store.STORE.NAME)
|
||||
.values(1, "ABC Branch I ")
|
||||
.values(2, "ABC Branch II")
|
||||
.execute();
|
||||
|
||||
context.insertInto(Tables.BOOK, Book.BOOK.ID, Book.BOOK.TITLE, Book.BOOK.DESCRIPTION, Book.BOOK.AUTHOR_ID, Book.BOOK.STORE_ID)
|
||||
.values(1, "Book 1", "This is book 1", 1, 1)
|
||||
.values(2, "Book 2", "This is book 2", 2, 2)
|
||||
.values(3, "Book 3", "This is book 3", 1, 2)
|
||||
.values(4, "Book 4", "This is book 4", 5, 1)
|
||||
.execute();
|
||||
|
||||
context.insertInto(Tables.BOOKAUTHOR, Bookauthor.BOOKAUTHOR.ID, Bookauthor.BOOKAUTHOR.NAME, Bookauthor.BOOKAUTHOR.COUNTRY)
|
||||
.values(1, "John Smith", "Japan")
|
||||
.values(2, "William Walce", "Japan")
|
||||
.values(3, "Marry Sity", "South Korea")
|
||||
.values(4, "Morry Toh", "England")
|
||||
.execute();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanup() throws Exception {
|
||||
context.truncateTable(Store.STORE)
|
||||
.execute();
|
||||
context.truncateTable(Book.BOOK)
|
||||
.execute();
|
||||
context.truncateTable(Bookauthor.BOOKAUTHOR)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void _whenUsingJoinMethod_thenQueryExecuted() {
|
||||
Result<Record> result = JoinTables.usingJoinMethod(context);
|
||||
assertEquals(3, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void _whenUsingMultipleJoinMethod_thenQueryExecuted() {
|
||||
Result<Record> result = JoinTables.usingMultipleJoinMethod(context);
|
||||
assertEquals(3, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenContext_whenUsingLeftOuterJoinMethod_thenQueryExecuted() {
|
||||
Result<Record> result = JoinTables.usingLeftOuterJoinMethod(context);
|
||||
assertEquals(4, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingRightOuterJoinMethod_thenQueryExecuted() {
|
||||
Result<Record> result = JoinTables.usingRightOuterJoinMethod(context);
|
||||
assertEquals(5, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingFullOuterJoinMethod_thenQueryExecuted() {
|
||||
Result<Record> result = JoinTables.usingFullOuterJoinMethod(context);
|
||||
assertEquals(6, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingNaturalJoinMethod_thenQueryExecuted() {
|
||||
Result<Record> result = JoinTables.usingNaturalJoinMethod(context);
|
||||
assertEquals(4, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingCrossJoinMethod_thenQueryExecuted() {
|
||||
Result<Record> result = JoinTables.usingCrossJoinMethod(context);
|
||||
assertEquals(8, result.size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.15.0.xsd">
|
||||
<jdbc>
|
||||
<driver>org.postgresql.Driver</driver>
|
||||
<url>jdbc:postgresql://localhost:5432/postgres</url>
|
||||
<user>postgres</user>
|
||||
<password></password>
|
||||
</jdbc>
|
||||
<generator>
|
||||
<database>
|
||||
<name>org.jooq.meta.postgres.PostgresDatabase</name>
|
||||
<includes>Store|Book|BookAuthor</includes>
|
||||
<excludes></excludes>
|
||||
</database>
|
||||
<target>
|
||||
<packageName>com.baeldung.jooq.jointables</packageName>
|
||||
<directory>src/main/java</directory>
|
||||
</target>
|
||||
</generator>
|
||||
</configuration>
|
||||
@@ -1,2 +1,3 @@
|
||||
### Relevant Articles:
|
||||
- [Introduction to Liquibase Rollback](http://www.baeldung.com/liquibase-rollback)
|
||||
- [Creating PostgreSQL Schema Before Liquibase Execution](https://www.baeldung.com/java-postgresql-create-schema-before-liquibase)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<module>core-java-persistence-2</module>
|
||||
<module>core-java-persistence-3</module>
|
||||
<module>couchbase</module>
|
||||
<module>duckdb</module>
|
||||
<module>elasticsearch</module>
|
||||
<module>flyway</module>
|
||||
<module>flyway-repair</module>
|
||||
@@ -88,6 +89,7 @@
|
||||
<module>spring-data-jpa-query</module>
|
||||
<module>spring-data-jpa-query-2</module>
|
||||
<module>spring-data-jpa-query-3</module>
|
||||
<module>spring-data-jpa-query-4</module>
|
||||
<module>spring-data-jpa-repo</module>
|
||||
<module>spring-data-jpa-repo-2</module>
|
||||
<module>spring-data-jpa-repo-4</module>
|
||||
|
||||
@@ -60,6 +60,11 @@
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${spring.tx.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -84,6 +89,7 @@
|
||||
<modelmapper.version>3.2.0</modelmapper.version>
|
||||
<commons-codec.version>1.16.1</commons-codec.version>
|
||||
<lombok.version>1.18.30</lombok.version>
|
||||
<spring.tx.version>6.1.4</spring.tx.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.baeldung.transactionalandasync;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Entity
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode(of = {"id"})
|
||||
@Table(name = "account")
|
||||
@Data
|
||||
public class Account {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
|
||||
@Column(name = "balance")
|
||||
private BigDecimal balance;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.baeldung.transactionalandasync;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface AccountRepository extends JpaRepository<Account, Long> {
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.transactionalandasync;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
@Transactional
|
||||
public class AccountService {
|
||||
|
||||
private final AccountRepository accountRepository;
|
||||
|
||||
@Async
|
||||
public void transferAsync(Long depositorId, Long favoredId, BigDecimal amount) {
|
||||
transfer(depositorId, favoredId, amount);
|
||||
|
||||
printReceipt();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void transfer(Long depositorId, Long favoredId, BigDecimal amount) {
|
||||
Account depositorAccount = accountRepository.findById(depositorId)
|
||||
.orElseThrow(IllegalArgumentException::new);
|
||||
Account favoredAccount = accountRepository.findById(favoredId)
|
||||
.orElseThrow(IllegalArgumentException::new);
|
||||
|
||||
depositorAccount.setBalance(depositorAccount.getBalance().subtract(amount));
|
||||
favoredAccount.setBalance(favoredAccount.getBalance().add(amount));
|
||||
|
||||
accountRepository.save(depositorAccount);
|
||||
accountRepository.save(favoredAccount);
|
||||
}
|
||||
|
||||
public void printReceipt() {
|
||||
// logic to print the receipt
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.transactionalandasync;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class BankAccountApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BankAccountApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -70,7 +70,6 @@
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<mockito.version>2.23.0</mockito.version>
|
||||
<validation-api.version>2.0.1.Final</validation-api.version>
|
||||
<mysql-connector-java.version>8.2.0</mysql-connector-java.version>
|
||||
<start-class>com.baeldung.boot.Application</start-class>
|
||||
|
||||
@@ -136,6 +136,12 @@
|
||||
<type>so</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.14.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
-2
@@ -5,8 +5,6 @@ import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.baeldung.Application;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class SpringContextTest {
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.criteriaquery;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
@Entity
|
||||
public class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
private String title;
|
||||
private String author;
|
||||
|
||||
public Book(String title, String author) {
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Book() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
static Specification<Book> hasAuthor(String author) {
|
||||
return (book, cq, cb) -> cb.equal(book.get("author"), author);
|
||||
}
|
||||
|
||||
static Specification<Book> titleContains(String title) {
|
||||
return (book, cq, cb) -> cb.like(book.get("title"), "%" + title + "%");
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.criteriaquery;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
interface BookRepository extends JpaRepository<Book, Long>, BookRepositoryCustom, JpaSpecificationExecutor<Book> {
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.criteriaquery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
interface BookRepositoryCustom {
|
||||
|
||||
List<Book> findBooksByAuthorNameAndTitle(String authorName, String title);
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.baeldung.criteriaquery;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public class BookRepositoryImpl implements BookRepositoryCustom {
|
||||
|
||||
@Autowired
|
||||
private EntityManager em;
|
||||
|
||||
@Override
|
||||
public List<Book> findBooksByAuthorNameAndTitle(String authorName, String title) {
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<Book> cq = cb.createQuery(Book.class);
|
||||
|
||||
Root<Book> book = cq.from(Book.class);
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
|
||||
if (authorName != null) {
|
||||
predicates.add(cb.equal(book.get("author"), authorName));
|
||||
}
|
||||
if (title != null) {
|
||||
predicates.add(cb.like(book.get("title"), "%" + title + "%"));
|
||||
}
|
||||
cq.where(predicates.toArray(new Predicate[0]));
|
||||
|
||||
return em.createQuery(cq).getResultList();
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.criteriaquery;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.baeldung.criteriaquery.Book.hasAuthor;
|
||||
import static com.baeldung.criteriaquery.Book.titleContains;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.data.jpa.domain.Specification.where;
|
||||
|
||||
@DataJpaTest(showSql = false)
|
||||
@RunWith(SpringRunner.class)
|
||||
public class CriteriaQueryIntegrationTest {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
@Autowired
|
||||
private BookRepository repository;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
entityManager.persist(new Book("title1", "author1"));
|
||||
entityManager.persist(new Book("title2", "author2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAuthorAndTextInTitle_whenFindWithSpecification_ThenFound() {
|
||||
List<Book> books = repository.findAll(where(hasAuthor("author1")).and(titleContains("1")));
|
||||
assertEquals(1, books.size());
|
||||
assertEquals("author1", books.get(0).getAuthor());
|
||||
assertEquals("title1", books.get(0).getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAuthorAndTextInTitle_whenFindWithCriteriaQuery_ThenFound() {
|
||||
List<Book> books = repository.findBooksByAuthorNameAndTitle("author2", "2");
|
||||
assertEquals(1, books.size());
|
||||
assertEquals("author2", books.get(0).getAuthor());
|
||||
assertEquals("title2", books.get(0).getTitle());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?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-data-jpa-query-4</artifactId>
|
||||
<name>spring-data-jpa-query-4</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<postgresql.version>42.7.1</postgresql.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.spring.data.jpa.getnextseq;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
|
||||
@Entity
|
||||
public class MyEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mySeqGen")
|
||||
@SequenceGenerator(name = "mySeqGen", sequenceName = "my_sequence_name", allocationSize = 1)
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.spring.data.jpa.getnextseq;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class MyEntityApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MyEntityApplication.class);
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.spring.data.jpa.getnextseq;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {
|
||||
|
||||
@Query(value = "SELECT NEXTVAL('my_sequence_name')", nativeQuery = true)
|
||||
Long getNextSequenceValue();
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.spring.data.jpa.getnextseq;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class MyEntityService {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
public Long getNextSequenceValue(String sequenceName) {
|
||||
BigInteger nextValue = (BigInteger) entityManager.createNativeQuery("SELECT NEXTVAL(:sequenceName)")
|
||||
.setParameter("sequenceName", sequenceName)
|
||||
.getSingleResult();
|
||||
return nextValue.longValue();
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.spring.data.jpa.queryjsonb;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Product {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
@Column(columnDefinition = "jsonb")
|
||||
private String attributes;
|
||||
|
||||
public Product() {
|
||||
}
|
||||
|
||||
public Product(String name, String attributes) {
|
||||
this.name = name;
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
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 String getAttributes() {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public void setAttributes(String attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.spring.data.jpa.queryjsonb;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ProductApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ProductApplication.class);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.spring.data.jpa.queryjsonb;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ProductRepository extends JpaRepository<Product, Long>, JpaSpecificationExecutor<Product> {
|
||||
@Query(value = "SELECT * FROM product WHERE attributes ->> ?1 = ?2", nativeQuery = true)
|
||||
List<Product> findByAttribute(String key, String value);
|
||||
|
||||
@Query(value = "SELECT * FROM product WHERE attributes -> ?1 ->> ?2 = ?3", nativeQuery = true)
|
||||
List<Product> findByNestedAttribute(String key1, String key2, String value);
|
||||
|
||||
@Query(value = "SELECT * FROM product WHERE jsonb_extract_path_text(attributes, ?1) = ?2", nativeQuery = true)
|
||||
List<Product> findByJsonPath(String path, String value);
|
||||
|
||||
@Query(value = "SELECT * FROM product WHERE jsonb_extract_path_text(attributes, ?1, ?2) = ?3", nativeQuery = true)
|
||||
List<Product> findByNestedJsonPath(String key1, String key2, String value);
|
||||
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.spring.data.jpa.queryjsonb;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
public class ProductSpecification implements Specification<Product> {
|
||||
|
||||
private final String key;
|
||||
private final String value;
|
||||
|
||||
public ProductSpecification(String key, String value) {
|
||||
this.key = key; this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
|
||||
return cb.equal(cb.function("jsonb_extract_path_text", String.class, root.get("attributes"), cb.literal(key)), value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
|
||||
spring.datasource.username=postgres
|
||||
spring.datasource.password=
|
||||
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
|
||||
spring.jpa.hibernate.ddl-auto=create
|
||||
spring.jpa.show-sql=true
|
||||
|
||||
logging.level.org.hibernate.SQL=DEBUG
|
||||
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.baeldung.spring.data.jpa.getnextseq;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("test")
|
||||
@Sql(scripts = "/testsequence.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
|
||||
public class MyEntityRepositoryIntegrationTest {
|
||||
@Autowired
|
||||
private MyEntityRepository myEntityRepository;
|
||||
|
||||
@Autowired
|
||||
private MyEntityService myEntityService;
|
||||
|
||||
@Test
|
||||
void whenUsingSequenceGenerator_thenNextValueReturned() {
|
||||
MyEntity entity = new MyEntity();
|
||||
myEntityRepository.save(entity);
|
||||
|
||||
long generatedId = entity.getId();
|
||||
assertNotNull(generatedId);
|
||||
assertEquals(1L, generatedId);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void whenUsingCustomQuery_thenNextValueReturned() {
|
||||
long generatedId = myEntityRepository.getNextSequenceValue();
|
||||
assertNotNull(generatedId);
|
||||
assertEquals(1L, generatedId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingEntityManager_thenNextValueReturned() {
|
||||
long generatedId = myEntityService.getNextSequenceValue("my_sequence_name");
|
||||
assertNotNull(generatedId);
|
||||
assertEquals(1L, generatedId);
|
||||
}
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.baeldung.spring.data.jpa.queryjsonb;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.test.annotation.Commit;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("test")
|
||||
@Sql(scripts = "/testdata.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
|
||||
public class ProductRepositoryLiveTest {
|
||||
|
||||
@Autowired
|
||||
private ProductRepository productRepository;
|
||||
|
||||
@Test
|
||||
void whenFindByAttribute_thenReturnTheObject() {
|
||||
List<Product> redProducts = productRepository.findByAttribute("color", "red");
|
||||
|
||||
assertEquals(1, redProducts.size());
|
||||
assertEquals("Laptop", redProducts.get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindByNestedAttribute_thenReturnTheObject() {
|
||||
List<Product> electronicProducts = productRepository.findByNestedAttribute("details", "category", "electronics");
|
||||
|
||||
assertEquals(1, electronicProducts.size());
|
||||
assertEquals("Headphones", electronicProducts.get(0)
|
||||
.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindByJsonPath_thenReturnTheObject() {
|
||||
List<Product> redProducts = productRepository.findByJsonPath("color", "red");
|
||||
assertEquals(1, redProducts.size());
|
||||
assertEquals("Laptop", redProducts.get(0)
|
||||
.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenNestedJsonAttribute_whenFindByJsonPath_thenReturnTheObject() {
|
||||
List<Product> electronicProducts = productRepository.findByNestedJsonPath("details", "category", "electronics");
|
||||
assertEquals(1, electronicProducts.size());
|
||||
assertEquals("Headphones", electronicProducts.get(0)
|
||||
.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingJPASpecification_thenReturnTheObject() {
|
||||
ProductSpecification spec = new ProductSpecification("color", "red");
|
||||
Page<Product> redProducts = productRepository.findAll(spec, Pageable.unpaged());
|
||||
|
||||
assertEquals(1, redProducts.getContent()
|
||||
.size());
|
||||
assertEquals("Laptop", redProducts.getContent()
|
||||
.get(0)
|
||||
.getName());
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
|
||||
spring.datasource.username=postgres
|
||||
spring.datasource.password=
|
||||
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
|
||||
spring.jpa.hibernate.ddl-auto=create
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
|
||||
logging.level.org.hibernate.SQL=DEBUG
|
||||
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
|
||||
@@ -0,0 +1,13 @@
|
||||
DELETE FROM product;
|
||||
|
||||
INSERT INTO product (name, attributes)
|
||||
VALUES ('Laptop', '{"color": "red", "size": "15 inch"}');
|
||||
|
||||
INSERT INTO product (name, attributes)
|
||||
VALUES ('Phone', '{"color": "blue", "size": "6 inch"}');
|
||||
|
||||
INSERT INTO product (name, attributes)
|
||||
VALUES ('Headphones', '{"brand": "Sony", "details": {"category": "electronics", "model": "WH-1000XM4"}}');
|
||||
|
||||
INSERT INTO product (name, attributes)
|
||||
VALUES ('Laptop', '{"brand": "Dell", "details": {"category": "computers", "model": "XPS 13"}}');
|
||||
@@ -0,0 +1,3 @@
|
||||
DROP SEQUENCE IF EXISTS my_sequence_name;
|
||||
|
||||
CREATE SEQUENCE my_sequence_name START 1;
|
||||
@@ -7,4 +7,6 @@
|
||||
- [Difference Between JPA and Spring Data JPA](https://www.baeldung.com/spring-data-jpa-vs-jpa)
|
||||
- [Differences Between Spring Data JPA findFirst() and findTop()](https://www.baeldung.com/spring-data-jpa-findfirst-vs-findtop)
|
||||
- [Difference Between findBy and findAllBy in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-find-by-vs-find-all-by)
|
||||
- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures)
|
||||
|
||||
- More articles: [[<-- prev]](../spring-data-jpa-repo)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.storedprocedure;
|
||||
package com.baeldung.spring.data.persistence.storedprocedure;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
+4
-5
@@ -1,14 +1,13 @@
|
||||
package com.baeldung.storedprocedure.controller;
|
||||
|
||||
import java.util.List;
|
||||
package com.baeldung.spring.data.persistence.storedprocedure.controller;
|
||||
|
||||
import com.baeldung.spring.data.persistence.storedprocedure.entity.Car;
|
||||
import com.baeldung.spring.data.persistence.storedprocedure.service.CarService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.baeldung.storedprocedure.entity.Car;
|
||||
import com.baeldung.storedprocedure.service.CarService;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class CarController {
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.storedprocedure.entity;
|
||||
package com.baeldung.spring.data.persistence.storedprocedure.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
+3
-4
@@ -1,14 +1,13 @@
|
||||
package com.baeldung.storedprocedure.repository;
|
||||
|
||||
import java.util.List;
|
||||
package com.baeldung.spring.data.persistence.storedprocedure.repository;
|
||||
|
||||
import com.baeldung.spring.data.persistence.storedprocedure.entity.Car;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.jpa.repository.query.Procedure;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.baeldung.storedprocedure.entity.Car;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface CarRepository extends JpaRepository<Car, Integer> {
|
||||
+4
-5
@@ -1,12 +1,11 @@
|
||||
package com.baeldung.storedprocedure.service;
|
||||
|
||||
import java.util.List;
|
||||
package com.baeldung.spring.data.persistence.storedprocedure.service;
|
||||
|
||||
import com.baeldung.spring.data.persistence.storedprocedure.entity.Car;
|
||||
import com.baeldung.spring.data.persistence.storedprocedure.repository.CarRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baeldung.storedprocedure.entity.Car;
|
||||
import com.baeldung.storedprocedure.repository.CarRepository;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CarService {
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery;
|
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
|
||||
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
|
||||
emf.setDataSource(dataSource);
|
||||
emf.setPackagesToScan("com.baeldung.spring.data.jpa.joinquery.entities"
|
||||
, "com.baeldung.spring.data.jpa.joinquery.DTO"
|
||||
, "com.baeldung.spring.data.jpa.joinquery.repositories");
|
||||
emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
|
||||
emf.setJpaProperties(getHibernateProperties());
|
||||
return emf;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean entityManagerFactory) {
|
||||
return new JpaTransactionManager(entityManagerFactory.getObject());
|
||||
}
|
||||
|
||||
private Properties getHibernateProperties() {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("hibernate.hbm2ddl.auto", "create");
|
||||
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery.DTO;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
class DTO {
|
||||
private Long customer_id;
|
||||
private Long order_id;
|
||||
private Long product_id;
|
||||
|
||||
public DTO(Long customer_id, Long order_id, Long product_id) {
|
||||
this.customer_id = customer_id;
|
||||
this.order_id = order_id;
|
||||
this.product_id = product_id;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
@IdClass(DTO.class)
|
||||
public class ResultDTO {
|
||||
@Id
|
||||
private Long customer_id;
|
||||
|
||||
@Id
|
||||
private Long order_id;
|
||||
|
||||
@Id
|
||||
private Long product_id;
|
||||
|
||||
public void setCustomer_id(Long customer_id) {
|
||||
this.customer_id = customer_id;
|
||||
}
|
||||
|
||||
public Long getProduct_id() {
|
||||
return product_id;
|
||||
}
|
||||
|
||||
public void setProduct_id(Long product_id) {
|
||||
this.product_id = product_id;
|
||||
}
|
||||
|
||||
public ResultDTO(Long customer_id, Long order_id, Long product_id, String customerName, String customerEmail, LocalDate orderDate, String productName, Double productPrice) {
|
||||
this.customer_id = customer_id;
|
||||
this.order_id = order_id;
|
||||
this.product_id = product_id;
|
||||
this.customerName = customerName;
|
||||
this.customerEmail = customerEmail;
|
||||
this.orderDate = orderDate;
|
||||
this.productName = productName;
|
||||
this.productPrice = productPrice;
|
||||
}
|
||||
|
||||
private String customerName;
|
||||
private String customerEmail;
|
||||
private LocalDate orderDate;
|
||||
private String productName;
|
||||
private Double productPrice;
|
||||
|
||||
public Long getCustomer_id() {
|
||||
return customer_id;
|
||||
}
|
||||
|
||||
public void setCustoemr_id(Long custoemr_id) {
|
||||
this.customer_id = custoemr_id;
|
||||
}
|
||||
|
||||
public String getCustomerName() {
|
||||
return customerName;
|
||||
}
|
||||
|
||||
public void setCustomerName(String customerName) {
|
||||
this.customerName = customerName;
|
||||
}
|
||||
|
||||
public String getCustomerEmail() {
|
||||
return customerEmail;
|
||||
}
|
||||
|
||||
public void setCustomerEmail(String customerEmail) {
|
||||
this.customerEmail = customerEmail;
|
||||
}
|
||||
|
||||
public Long getOrder_id() {
|
||||
return order_id;
|
||||
}
|
||||
|
||||
public void setOrder_id(Long order_id) {
|
||||
this.order_id = order_id;
|
||||
}
|
||||
|
||||
public LocalDate getOrderDate() {
|
||||
return orderDate;
|
||||
}
|
||||
|
||||
public void setOrderDate(LocalDate orderDate) {
|
||||
this.orderDate = orderDate;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
return productName;
|
||||
}
|
||||
|
||||
public void setProductName(String productName) {
|
||||
this.productName = productName;
|
||||
}
|
||||
|
||||
public Double getProductPrice() {
|
||||
return productPrice;
|
||||
}
|
||||
|
||||
public void setProductPrice(Double productPrice) {
|
||||
this.productPrice = productPrice;
|
||||
}
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery.DTO;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
//@Entity
|
||||
//@IdClass(DTO.class)
|
||||
public class ResultDTO_wo_Ids {
|
||||
public ResultDTO_wo_Ids(String customerName, String customerEmail, LocalDate orderDate, String productName, Double productPrice) {
|
||||
this.customerName = customerName;
|
||||
this.customerEmail = customerEmail;
|
||||
this.orderDate = orderDate;
|
||||
this.productName = productName;
|
||||
this.productPrice = productPrice;
|
||||
}
|
||||
|
||||
private String customerName;
|
||||
private String customerEmail;
|
||||
private LocalDate orderDate;
|
||||
private String productName;
|
||||
private Double productPrice;
|
||||
|
||||
public String getCustomerName() {
|
||||
return customerName;
|
||||
}
|
||||
|
||||
public void setCustomerName(String customerName) {
|
||||
this.customerName = customerName;
|
||||
}
|
||||
|
||||
public String getCustomerEmail() {
|
||||
return customerEmail;
|
||||
}
|
||||
|
||||
public void setCustomerEmail(String customerEmail) {
|
||||
this.customerEmail = customerEmail;
|
||||
}
|
||||
|
||||
public LocalDate getOrderDate() {
|
||||
return orderDate;
|
||||
}
|
||||
|
||||
public void setOrderDate(LocalDate orderDate) {
|
||||
this.orderDate = orderDate;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
return productName;
|
||||
}
|
||||
|
||||
public void setProductName(String productName) {
|
||||
this.productName = productName;
|
||||
}
|
||||
|
||||
public Double getProductPrice() {
|
||||
return productPrice;
|
||||
}
|
||||
|
||||
public void setProductPrice(Double productPrice) {
|
||||
this.productPrice = productPrice;
|
||||
}
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
public class Customer {
|
||||
public Customer(){}
|
||||
@Id
|
||||
//@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@OneToMany(mappedBy = "customer"
|
||||
, cascade = CascadeType.ALL)
|
||||
private Set<CustomerOrder> customerOrders;
|
||||
|
||||
public Customer(Long id, Set<CustomerOrder> customerOrders, String email, LocalDate dob, String name) {
|
||||
this.id = id;
|
||||
this.customerOrders = customerOrders;
|
||||
this.email = email;
|
||||
this.dob = dob;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setCustomerOrders(Set<CustomerOrder> customerOrders) {
|
||||
this.customerOrders = customerOrders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Patient{" +
|
||||
"id=" + id +
|
||||
", orders=" + customerOrders +
|
||||
", email='" + email + '\'' +
|
||||
", dob=" + dob +
|
||||
", name='" + name + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
public Set<CustomerOrder> getOrders() {
|
||||
return customerOrders;
|
||||
}
|
||||
|
||||
public void setOrders(Set<CustomerOrder> orders) {
|
||||
this.customerOrders = orders;
|
||||
}
|
||||
|
||||
@Column
|
||||
private String email;
|
||||
|
||||
@Column(name = "dob", columnDefinition = "DATE")
|
||||
private LocalDate dob;
|
||||
|
||||
@Column
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Customer patient = (Customer) o;
|
||||
return Objects.equals(id, patient.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public LocalDate getDob() {
|
||||
return dob;
|
||||
}
|
||||
|
||||
public void setDob(LocalDate dob) {
|
||||
this.dob = dob;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
public class CustomerOrder {
|
||||
public CustomerOrder(){}
|
||||
@Id
|
||||
//@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<Product> getProducts() {
|
||||
return products;
|
||||
}
|
||||
|
||||
public void setProducts(Set<Product> products) {
|
||||
this.products = products;
|
||||
}
|
||||
|
||||
@OneToMany(mappedBy = "customerOrder"
|
||||
, cascade = CascadeType.ALL)
|
||||
private Set<Product> products;
|
||||
|
||||
@Column
|
||||
private LocalDate orderDate;
|
||||
|
||||
public CustomerOrder(Long id, Set<Product> products, LocalDate orderDate, Customer customer) {
|
||||
this.id = id;
|
||||
this.products = products;
|
||||
this.orderDate = orderDate;
|
||||
this.customer = customer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Consult{" +
|
||||
"id=" + id +
|
||||
", products=" + products +
|
||||
", orderDate=" + orderDate +
|
||||
", customer=" + customer +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
CustomerOrder co = (CustomerOrder) o;
|
||||
return Objects.equals(id, co.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name="customer_id", nullable = false)
|
||||
private Customer customer;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public LocalDate getOrderDate() {
|
||||
return orderDate;
|
||||
}
|
||||
|
||||
public void setOrderDate(LocalDate orderDate) {
|
||||
this.orderDate = orderDate;
|
||||
}
|
||||
|
||||
public Customer getCustomer() {
|
||||
return customer;
|
||||
}
|
||||
|
||||
public void setCustomer(Customer customer) {
|
||||
this.customer = customer;
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Product {
|
||||
public Product(){}
|
||||
@Id
|
||||
//@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
public Product(Long id, String productName, Double price, CustomerOrder customerOrder) {
|
||||
this.id = id;
|
||||
this.productName = productName;
|
||||
this.price = price;
|
||||
this.customerOrder = customerOrder;
|
||||
}
|
||||
|
||||
@Column
|
||||
private String productName;
|
||||
|
||||
@Column
|
||||
private Double price;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Dispense{" +
|
||||
"id=" + id +
|
||||
", productName='" + productName + '\'' +
|
||||
", price=" + price +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Product dispense = (Product) o;
|
||||
return Objects.equals(id, dispense.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
return productName;
|
||||
}
|
||||
|
||||
public void setProductName(String productName) {
|
||||
this.productName = productName;
|
||||
}
|
||||
|
||||
public Double getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(Double price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public CustomerOrder getCustomerOrder() {
|
||||
return customerOrder;
|
||||
}
|
||||
|
||||
public void setCustomerOrder(CustomerOrder co) {
|
||||
this.customerOrder = co;
|
||||
}
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name="customerorder_id", nullable = false)
|
||||
private CustomerOrder customerOrder;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery.repositories;
|
||||
|
||||
import com.baeldung.spring.data.jpa.joinquery.entities.Customer;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface CustomerRepository extends CrudRepository<Customer, Long> {
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery.repositories;
|
||||
|
||||
import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO;
|
||||
import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO_wo_Ids;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Repository
|
||||
public interface JoinRepository extends CrudRepository<ResultDTO, Long> {
|
||||
@Query(value = "SELECT new com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO(c.id, o.id, p.id, c.name, c.email, o.orderDate, p.productName, p.price) "
|
||||
+ " from Customer c, CustomerOrder o ,Product p "
|
||||
+ " where c.id=o.customer.id "
|
||||
+ " and o.id=p.customerOrder.id "
|
||||
+ " and c.id=?1 ")
|
||||
List<ResultDTO> findResultDTOByCustomer(Long id);
|
||||
|
||||
@Query(value = "SELECT new com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO_wo_Ids(c.name, c.email, o.orderDate, p.productName, p.price) "
|
||||
+ " from Customer c, CustomerOrder o ,Product p "
|
||||
+ " where c.id=o.customer.id "
|
||||
+ " and o.id=p.customerOrder.id "
|
||||
+ " and c.id=?1 ")
|
||||
List<ResultDTO_wo_Ids> findResultDTOByCustomerWithoutIds(Long id);
|
||||
|
||||
@Query(value = "SELECT c.*, o.*, p.* "
|
||||
+ " from Customer c, CustomerOrder o ,Product p "
|
||||
+ " where c.id=o.customer_id "
|
||||
+ " and o.id=p.customerOrder_id "
|
||||
+ " and c.id=?1 "
|
||||
, nativeQuery = true)
|
||||
List<Map<String, Object>> findByCustomer(Long id);
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package com.baeldung.spring.data.jpa.joinquery;
|
||||
|
||||
import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO_wo_Ids;
|
||||
import com.baeldung.spring.data.jpa.joinquery.entities.Customer;
|
||||
import com.baeldung.spring.data.jpa.joinquery.entities.CustomerOrder;
|
||||
import com.baeldung.spring.data.jpa.joinquery.DTO.ResultDTO;
|
||||
import com.baeldung.spring.data.jpa.joinquery.entities.Product;
|
||||
import com.baeldung.spring.data.jpa.joinquery.repositories.CustomerRepository;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import jakarta.persistence.EntityTransaction;
|
||||
import jakarta.persistence.PersistenceUnit;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import com.baeldung.spring.data.jpa.joinquery.repositories.JoinRepository;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = { AppConfig.class })
|
||||
class JoinRepositoryUnitTest {
|
||||
|
||||
@Autowired
|
||||
JoinRepository joinRepository;
|
||||
|
||||
@Autowired
|
||||
CustomerRepository customerRepository;
|
||||
|
||||
@PersistenceUnit
|
||||
EntityManagerFactory entityManagerFactory;
|
||||
|
||||
EntityManager entityManager;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
customerRepository.deleteAll();
|
||||
entityManager = entityManagerFactory.createEntityManager();
|
||||
Customer c = new Customer(1L, null, "email1@email.com", LocalDate.now(), "Customer");
|
||||
CustomerOrder o1 = new CustomerOrder(1L, null, LocalDate.now(), c);
|
||||
CustomerOrder o2 = new CustomerOrder(2L, null, LocalDate.of(2024,1,1), c);
|
||||
|
||||
Product p1 = new Product(1L,"Product1", 25.20, o1);
|
||||
Product p2 = new Product(2L, "Product2", 26.20, o1);
|
||||
Product p3 = new Product(3L, "Product3", 27.20, o2);
|
||||
|
||||
Set<CustomerOrder> cos01 = new HashSet<>();
|
||||
cos01.add(o1);
|
||||
cos01.add(o2);
|
||||
Set<Product> productsO1 = new HashSet<>();
|
||||
productsO1.add(p1);
|
||||
productsO1.add(p2);
|
||||
Set<Product> productsO2 = new HashSet<>();
|
||||
productsO1.add(p3);
|
||||
|
||||
c.setCustomerOrders(cos01);
|
||||
o1.setProducts(productsO1);
|
||||
o2.setProducts(productsO2);
|
||||
|
||||
EntityTransaction et = getTransaction();
|
||||
entityManager.persist(c);
|
||||
entityManager.flush();
|
||||
et.commit();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindResultDTOByCustomer_thenReturnResultDTO() {
|
||||
List<ResultDTO> resultDTO = joinRepository.findResultDTOByCustomer(1L);
|
||||
assertInstanceOf(ResultDTO.class, resultDTO.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindByCustomerNativeQuery_thenReturnMapsForObjects() {
|
||||
List<Map<String, Object>> res = joinRepository.findByCustomer(1L);
|
||||
//the map objects in the res List has 9 String keys aka 9 columns corresponding to the columns of customer, customerOrder, product
|
||||
res.forEach(map -> {
|
||||
assertEquals(9, map.keySet().size());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFindResultDTOByCustomerWithoutIds_thenReturnResultDTO() {
|
||||
List<ResultDTO_wo_Ids> resultDTO = joinRepository.findResultDTOByCustomerWithoutIds(1L);
|
||||
assertInstanceOf(ResultDTO_wo_Ids.class, resultDTO.get(0));
|
||||
}
|
||||
|
||||
private EntityTransaction getTransaction() {
|
||||
EntityTransaction transaction = entityManager.getTransaction();
|
||||
transaction.begin();
|
||||
return transaction;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ This module contains articles about repositories in Spring Data JPA
|
||||
- [Spring Data JPA – Adding a Method in All Repositories](https://www.baeldung.com/spring-data-jpa-method-in-all-repositories)
|
||||
- [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)
|
||||
- [LIKE Queries in Spring JPA Repositories](https://www.baeldung.com/spring-jpa-like-queries)
|
||||
|
||||
- More articles: [[--> next]](../spring-data-jpa-repo-2)
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableJpaRepositories("com.baeldung.jpa.modifying")
|
||||
@EntityScan("com.baeldung.jpa.modifying")
|
||||
@EnableJpaRepositories("com.baeldung.jpa.modifying.repository")
|
||||
@EntityScan("com.baeldung.jpa.modifying.model")
|
||||
public class ModifyingApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
+1
-3
@@ -78,9 +78,7 @@ public class Possession {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]");
|
||||
return builder.toString();
|
||||
return "Possession [id=" + id + ", name=" + name + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-3
@@ -96,9 +96,7 @@ public class User {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("User [name=").append(name).append(", id=").append(id).append("]");
|
||||
return builder.toString();
|
||||
return "User [name=" + name + ", id=" + id + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.modifying.dao;
|
||||
package com.baeldung.jpa.modifying.repository;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.paginationsorting;
|
||||
package com.baeldung.jpa.paginationsorting.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
+2
-4
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.query;
|
||||
package com.baeldung.jpa.query.model;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
@@ -106,9 +106,7 @@ public class User {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("User [name=").append(name).append(", id=").append(id).append("]");
|
||||
return builder.toString();
|
||||
return "User [name=" + name + ", id=" + id + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.query;
|
||||
package com.baeldung.jpa.query.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -12,6 +12,8 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.baeldung.jpa.query.model.User;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends JpaRepository<User, Integer>, UserRepositoryCustom {
|
||||
@Query("SELECT u FROM User u WHERE u.status = 1")
|
||||
+3
-1
@@ -1,10 +1,12 @@
|
||||
package com.baeldung.jpa.query;
|
||||
package com.baeldung.jpa.query.repository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.baeldung.jpa.query.model.User;
|
||||
|
||||
public interface UserRepositoryCustom {
|
||||
|
||||
List<User> findUserByEmails(Set<String> emails);
|
||||
+3
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.query;
|
||||
package com.baeldung.jpa.query.repository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -7,6 +7,8 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.baeldung.jpa.query.model.User;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class PersistenceConfig {
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource());
|
||||
em.setPackagesToScan("com.baeldung.jpa.simple.entity");
|
||||
em.setPackagesToScan("com.baeldung.jpa.simple.model");
|
||||
|
||||
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
em.setJpaVendorAdapter(vendorAdapter);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.simple.entity;
|
||||
package com.baeldung.jpa.simple.model;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.simple.entity;
|
||||
package com.baeldung.jpa.simple.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.jpa.simple.entity;
|
||||
package com.baeldung.jpa.simple.model;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import java.util.List;
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.baeldung.jpa.simple.entity.Book;
|
||||
import com.baeldung.jpa.simple.model.Book;
|
||||
|
||||
@Repository
|
||||
public interface BookListRepository extends ListCrudRepository<Book, Long> {
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import org.springframework.data.repository.ListCrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.baeldung.jpa.simple.entity.Book;
|
||||
import com.baeldung.jpa.simple.model.Book;
|
||||
|
||||
@Repository
|
||||
public interface BookPagingAndSortingRepository extends PagingAndSortingRepository<Book, Long>, ListCrudRepository<Book, Long> {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user