View Javadoc
1   /*
2    * Copyright (c) 2022-2023. Roland T. Lichti, Kaiserpfalz EDV-Service.
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU General Public License as published by
6    * the Free Software Foundation, either version 3 of the License, or
7    * (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16   */
17  
18  package de.kaiserpfalzedv.commons.jpa;
19  
20  import java.io.Serializable;
21  import java.time.OffsetDateTime;
22  import java.util.Objects;
23  
24  import org.hibernate.annotations.CreationTimestamp;
25  import org.hibernate.annotations.UpdateTimestamp;
26  
27  import de.kaiserpfalzedv.commons.api.resources.HasId;
28  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
29  import jakarta.annotation.Nullable;
30  import jakarta.persistence.Column;
31  import jakarta.persistence.GeneratedValue;
32  import jakarta.persistence.Id;
33  import jakarta.persistence.MappedSuperclass;
34  import jakarta.persistence.Version;
35  import lombok.AllArgsConstructor;
36  import lombok.Builder;
37  import lombok.Getter;
38  import lombok.NoArgsConstructor;
39  import lombok.NonNull;
40  import lombok.Setter;
41  import lombok.ToString;
42  import lombok.experimental.SuperBuilder;
43  
44  @SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "lombok provided superbuilder constructor.")
45  @MappedSuperclass
46  @SuperBuilder(toBuilder = true)
47  @AllArgsConstructor
48  @NoArgsConstructor
49  @Getter
50  @Setter
51  @ToString(callSuper = true)
52  public abstract class AbstractJPAEntity<T extends Serializable> implements HasId<T>, Cloneable {
53      @Id
54      @GeneratedValue
55      @Column(name = "ID", nullable = false, insertable = true, updatable = false, unique = true)
56      protected T id;
57  
58      @NonNull
59      @Version
60      @Column(name = "VERSION", nullable = false, insertable = true, updatable = true)
61      @Builder.Default
62      protected Integer version = 0;
63  
64      @CreationTimestamp
65      @Column(name = "CREATED", nullable = false, insertable = true, updatable = false)
66      protected OffsetDateTime created;
67  
68      @UpdateTimestamp
69      @Column(name = "MODIFIED", nullable = true, insertable = false, updatable = true)
70      protected OffsetDateTime modified;
71  
72      @Column(name = "DELETED", nullable = true, insertable = false, updatable = true)
73      @Nullable
74      protected OffsetDateTime deleted;
75  
76  
77      @SuppressWarnings({"unchecked","java:S2097"})
78      @Override
79      public boolean equals(final Object o) {
80          if (this == o) return true;
81          if (o == null) return false;
82          if (!(AbstractJPAEntity.class.isAssignableFrom(o.getClass()))) return false;
83  
84          return this.id.equals(((HasId<T>)o).getId());
85      }
86  
87      @Override
88      public int hashCode() {
89          return Objects.hash(this.getId());
90      }
91  
92      @Override
93      @SuppressWarnings("java:S2975")
94      protected AbstractJPAEntity<T> clone() throws CloneNotSupportedException {
95          @SuppressWarnings("unchecked")
96          final AbstractJPAEntity<T> result = (AbstractJPAEntity<T>) super.clone();
97  
98          result.id = this.id;
99          result.version = this.version;
100 
101         if (this.created != null) {
102             result.created = this.created;
103         }
104 
105         if (this.modified != null) {
106             result.modified = this.modified;
107         }
108 
109         return result;
110     }
111 }