1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 }