Skip to content

Commit

Permalink
Hibernate support (#2147)
Browse files Browse the repository at this point in the history
* Hibernate support

---------

Signed-off-by: Avgustin Marinov <[email protected]>
  • Loading branch information
avgustinmm authored Dec 16, 2024
1 parent af50e8c commit db3ac7f
Show file tree
Hide file tree
Showing 51 changed files with 1,397 additions and 704 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/verify-hibernate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Verify (Hibernate)

on:
push:
branches:
- master
paths-ignore:
- '.3rd-party/**'
- 'site/**'
- '**.md'
pull_request:
paths-ignore:
- '.3rd-party/**'
- 'site/**'
- '**.md'

jobs:
verify-hibernate:
runs-on: ubuntu-latest

services:
rabbitmq:
image: rabbitmq:3-management-alpine
env:
RABBITMQ_DEFAULT_VHOST: /
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
ports:
- 15672:15672
- 5672:5672

steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
cache: 'maven'

- name: Check file license headers
run: mvn license:check --batch-mode

- name: Run tests & javadoc
run: mvn verify javadoc:javadoc --batch-mode -Djpa.vendor=hibernate -Dlogging.level.org.hibernate.collection.spi.AbstractPersistentCollection=ERROR
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,7 @@ public ResponseEntity<PagedList<MgmtDistributionSet>> getDistributionSets(
}

@Override
public ResponseEntity<MgmtDistributionSet> getDistributionSet(
final Long distributionSetId) {
public ResponseEntity<MgmtDistributionSet> getDistributionSet(final Long distributionSetId) {
final DistributionSet foundDs = distributionSetManagement.getOrElseThrowException(distributionSetId);

final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(foundDs);
Expand All @@ -142,8 +141,7 @@ public ResponseEntity<MgmtDistributionSet> getDistributionSet(
}

@Override
public ResponseEntity<List<MgmtDistributionSet>> createDistributionSets(
final List<MgmtDistributionSetRequestBodyPost> sets) {
public ResponseEntity<List<MgmtDistributionSet>> createDistributionSets(final List<MgmtDistributionSetRequestBodyPost> sets) {
log.debug("creating {} distribution sets", sets.size());
// set default Ds type if ds type is null
final String defaultDsKey = systemSecurityContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,14 +746,4 @@ private DistributionSetType generateTestType() {
assertThat(testType.getMandatoryModuleTypes()).containsExactly(osType);
return testType;
}

private void createSoftwareModulesAlphabetical(final int amount) {
char character = 'a';
for (int index = 0; index < amount; index++) {
final String str = String.valueOf(character);
softwareModuleManagement.create(
entityFactory.softwareModule().create().name(str).description(str).vendor(str).version(str));
character++;
}
}
}
3 changes: 3 additions & 0 deletions hawkbit-repository/hawkbit-repository-jpa-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# hawkBit JPA EclipseLink Vendor integration

Implementation of [EclipseLink](http://www.eclipse.org/eclipselink/) JPA vendor.
54 changes: 54 additions & 0 deletions hawkbit-repository/hawkbit-repository-jpa-api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!--
Copyright (c) 2015 Bosch Software Innovations GmbH and others
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.hawkbit</groupId>
<version>${revision}</version>
<artifactId>hawkbit-repository</artifactId>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>hawkbit-repository-jpa-api</artifactId>
<name>hawkBit :: Repository :: JPA API</name>

<properties>
<apt.source.dir>${project.build.directory}/generated-sources/apt/</apt.source.dir>
</properties>

<dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository-core</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- Static class generation -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void afterCommit() {
@Override
@SuppressWarnings({ "squid:S1217" })
public void afterCompletion(final int status) {
log.debug("Transaction completed after commit with status {}", status == STATUS_COMMITTED ? "COMMITTED" : "ROLLEDBACK");
log.debug("Transaction completed after commit with status {}", status == TransactionSynchronization.STATUS_COMMITTED ? "COMMITTED" : "ROLLEDBACK");
}

private void afterCommit(final Runnable runnable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.jpa.model;

import java.io.Serializable;

import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.PostPersist;
import jakarta.persistence.PostRemove;
import jakarta.persistence.PostUpdate;

import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.context.SecurityContextHolder;

/**
* Core information of all entities.
*/
@MappedSuperclass
@EntityListeners({ AuditingEntityListener.class, EntityInterceptorListener.class })
public abstract class AbstractBaseEntity implements BaseEntity, Serializable {

/**
* Defined equals/hashcode strategy for the repository in general is that an entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*/
@Override
// Exception squid:S864 - generated code
@SuppressWarnings({ "squid:S864" })
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (getId() == null ? 0 : getId().hashCode());
result = prime * result + getOptLockRevision();
result = prime * result + getClass().getName().hashCode();
return result;
}

/**
* Defined equals/hashcode strategy for the repository in general is that an entity is equal if it has the same {@link #getId()} and
* {@link #getOptLockRevision()} and class.
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!getClass().isInstance(obj)) {
return false;
}
final BaseEntity other = (BaseEntity) obj;
final Long id = getId();
final Long otherId = other.getId();
if (id == null) {
if (otherId != null) {
return false;
}
} else if (!id.equals(otherId)) {
return false;
}
return getOptLockRevision() == other.getOptLockRevision();
}

@Override
public String toString() {
return getClass().getSimpleName() + " [id=" + getId() + "]";
}

@PostPersist
public void postInsert() {
if (this instanceof EventAwareEntity eventAwareEntity) {
doNotify(eventAwareEntity::fireCreateEvent);
}
}

@PostUpdate
public void postUpdate() {
if (this instanceof EventAwareEntity eventAwareEntity) {
doNotify(eventAwareEntity::fireUpdateEvent);
}
}

@PostRemove
public void postDelete() {
if (this instanceof EventAwareEntity eventAwareEntity) {
doNotify(eventAwareEntity::fireDeleteEvent);
}
}

protected static void doNotify(final Runnable runnable) {
// fire events onl AFTER transaction commit
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable);
}

protected boolean isController() {
return SecurityContextHolder.getContext().getAuthentication() != null
&& SecurityContextHolder.getContext().getAuthentication()
.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails
&& tenantAwareDetails.isController();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# hawkBit JPA EclipseLink Vendor integration

Implementation of [EclipseLink](http://www.eclipse.org/eclipselink/) JPA vendor.
49 changes: 49 additions & 0 deletions hawkbit-repository/hawkbit-repository-jpa-eclipselink/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<!--
Copyright (c) 2015 Bosch Software Innovations GmbH and others
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.hawkbit</groupId>
<version>${revision}</version>
<artifactId>hawkbit-repository</artifactId>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>hawkbit-repository-jpa-eclipselink</artifactId>
<name>hawkBit :: Repository :: JPA EclipseLink Vendor</name>

<properties>
<apt.source.dir>${project.build.directory}/generated-sources/apt/</apt.source.dir>
</properties>

<dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository-jpa-api</artifactId>
<version>${project.version}</version>
</dependency>

<!-- Static class generation -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>${eclipselink.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
* 3.b.) the cause is not an {@link SQLException} and as a result cannot be
* mapped.
*/
public class HawkbitEclipseLinkJpaDialect extends EclipseLinkJpaDialect {
class HawkbitEclipseLinkJpaDialect extends EclipseLinkJpaDialect {

@Serial
private static final long serialVersionUID = 1L;
Expand Down Expand Up @@ -99,4 +99,4 @@ private static SQLException findSqlException(final RuntimeException jpaSystemExc

return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,35 @@
import jakarta.persistence.Query;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
@Slf4j
public class Jpa {

public enum JpaVendor {
ECLIPSELINK,
HIBERNATE // NOT SUPPORTED!
HIBERNATE
}

public static final JpaVendor JPA_VENDOR = JpaVendor.ECLIPSELINK;
static {
log.info("JPA vendor: {}", JPA_VENDOR);
}

public static char NATIVE_QUERY_PARAMETER_PREFIX = switch (JPA_VENDOR) {
case ECLIPSELINK -> '?';
case HIBERNATE -> ':';
};
public static final char NATIVE_QUERY_PARAMETER_PREFIX = '?';

public static <T> String formatNativeQueryInClause(final String name, final List<T> list) {
return switch (Jpa.JPA_VENDOR) {
case ECLIPSELINK -> formatEclipseLinkNativeQueryInClause(IntStream.range(0, list.size()).mapToObj(i -> name + "_" + i).toList());
case HIBERNATE -> ":" + name;
};
return formatEclipseLinkNativeQueryInClause(IntStream.range(0, list.size()).mapToObj(i -> name + "_" + i).toList());
}

public static <T> void setNativeQueryInParameter(final Query deleteQuery, final String name, final List<T> list) {
if (Jpa.JPA_VENDOR == Jpa.JpaVendor.ECLIPSELINK) {
for (int i = 0, len = list.size(); i < len; i++) {
deleteQuery.setParameter(name + "_" + i, list.get(i));
}
} else if (Jpa.JPA_VENDOR == Jpa.JpaVendor.HIBERNATE) {
deleteQuery.setParameter(name, list);
for (int i = 0, len = list.size(); i < len; i++) {
deleteQuery.setParameter(name + "_" + i, list.get(i));
}
}

private static String formatEclipseLinkNativeQueryInClause(final Collection<String> elements) {
return "?" + String.join(",?", elements);
}
}
}
Loading

0 comments on commit db3ac7f

Please sign in to comment.