You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/07/17 06:14:42 UTC

[isis] branch ISIS-2801 updated: ISIS-2801: adds support for ClobJpaEmbeddable also

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-2801
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/ISIS-2801 by this push:
     new 48f4f37  ISIS-2801: adds support for ClobJpaEmbeddable also
48f4f37 is described below

commit 48f4f373ab899edcddda980409d7452f1e00a7e5
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Sat Jul 17 07:14:17 2021 +0100

    ISIS-2801: adds support for ClobJpaEmbeddable also
---
 .../dom/types/isis/blobs/jpa/IsisBlobJpa.java      |  20 ++--
 .../dom/types/isis/clobs/jpa/IsisClobJpa.java      | 116 +++++++++++++--------
 .../jpa/adoc/modules/ROOT/pages/mapping-guide.adoc |  50 +++++++--
 .../jpa/applib/types/BlobJpaEmbeddable.java        |  39 ++++---
 ...obJpaEmbeddable.java => ClobJpaEmbeddable.java} |  76 ++++++++------
 5 files changed, 189 insertions(+), 112 deletions(-)

diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jpa/IsisBlobJpa.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jpa/IsisBlobJpa.java
index 94b5e5e..0f1dc64 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jpa/IsisBlobJpa.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/blobs/jpa/IsisBlobJpa.java
@@ -18,8 +18,6 @@
  */
 package demoapp.dom.types.isis.blobs.jpa;
 
-import java.util.Optional;
-
 import javax.persistence.AttributeOverride;
 import javax.persistence.AttributeOverrides;
 import javax.persistence.Column;
@@ -38,7 +36,7 @@ import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.value.Blob;
 import org.apache.isis.persistence.jpa.applib.integration.IsisEntityListener;
-import org.apache.isis.persistence.jpa.integration.types.BlobJpaEmbeddable;
+import org.apache.isis.persistence.jpa.applib.types.BlobJpaEmbeddable;
 import org.springframework.context.annotation.Profile;
 
 import demoapp.dom.types.isis.blobs.persistence.IsisBlobEntity;
@@ -81,10 +79,10 @@ public class IsisBlobJpa
     @Title(prepend = "Blob JPA entity: ")
     @PropertyLayout(fieldSetId = "read-only-properties", sequence = "1")
     public Blob getReadOnlyProperty() {
-        return readOnlyProperty.toBlob();
+        return BlobJpaEmbeddable.toBlob(readOnlyProperty);
     }
     public void setReadOnlyProperty(final Blob readOnlyProperty) {
-        this.readOnlyProperty = BlobJpaEmbeddable.from(readOnlyProperty);
+        this.readOnlyProperty = BlobJpaEmbeddable.fromBlob(readOnlyProperty);
     }
 
     @AttributeOverrides({
@@ -98,11 +96,11 @@ public class IsisBlobJpa
     @Property(editing = Editing.ENABLED)                            // <.>
     @PropertyLayout(fieldSetId = "editable-properties", sequence = "1")
     public Blob getReadWriteProperty() {
-        return readWriteProperty.toBlob();
+        return BlobJpaEmbeddable.toBlob(readWriteProperty);
     }
 
     public void setReadWriteProperty(final Blob readWriteProperty) {
-        this.readWriteProperty = BlobJpaEmbeddable.from(readWriteProperty);
+        this.readWriteProperty = BlobJpaEmbeddable.fromBlob(readWriteProperty);
     }
 
     @AttributeOverrides({
@@ -116,11 +114,11 @@ public class IsisBlobJpa
     @Property(optionality = Optionality.OPTIONAL)                   // <.>
     @PropertyLayout(fieldSetId = "optional-properties", sequence = "1")
     public Blob getReadOnlyOptionalProperty() {
-        return Optional.ofNullable(readOnlyOptionalProperty).map(BlobJpaEmbeddable::toBlob).orElse(null);
+        return BlobJpaEmbeddable.toBlob(readOnlyOptionalProperty);
     }
 
     public void setReadOnlyOptionalProperty(final Blob readOnlyOptionalProperty) {
-        this.readOnlyOptionalProperty = BlobJpaEmbeddable.from(readOnlyOptionalProperty);
+        this.readOnlyOptionalProperty = BlobJpaEmbeddable.fromBlob(readOnlyOptionalProperty);
     }
 
 
@@ -135,11 +133,11 @@ public class IsisBlobJpa
     @Property(editing = Editing.ENABLED, optionality = Optionality.OPTIONAL)
     @PropertyLayout(fieldSetId = "optional-properties", sequence = "2")
     public Blob getReadWriteOptionalProperty() {
-        return Optional.ofNullable(readWriteOptionalProperty).map(BlobJpaEmbeddable::toBlob).orElse(null);
+        return BlobJpaEmbeddable.toBlob(readWriteOptionalProperty);
     }
 
     public void setReadWriteOptionalProperty(final Blob readWriteOptionalProperty) {
-        this.readWriteOptionalProperty = BlobJpaEmbeddable.from(readWriteOptionalProperty);
+        this.readWriteOptionalProperty = BlobJpaEmbeddable.fromBlob(readWriteOptionalProperty);
     }
 }
 //end::class[]
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jpa/IsisClobJpa.java b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jpa/IsisClobJpa.java
index 7fff14e..db5493e 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jpa/IsisClobJpa.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/types/isis/clobs/jpa/IsisClobJpa.java
@@ -18,14 +18,16 @@
  */
 package demoapp.dom.types.isis.clobs.jpa;
 
+import javax.persistence.AttributeOverride;
+import javax.persistence.AttributeOverrides;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
 import javax.persistence.Entity;
 import javax.persistence.EntityListeners;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.Table;
 
-import org.springframework.context.annotation.Profile;
-
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.Editing;
 import org.apache.isis.applib.annotation.Optionality;
@@ -34,11 +36,11 @@ import org.apache.isis.applib.annotation.PropertyLayout;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.value.Clob;
 import org.apache.isis.persistence.jpa.applib.integration.JpaEntityInjectionPointResolver;
+import org.apache.isis.persistence.jpa.applib.types.ClobJpaEmbeddable;
+import org.springframework.context.annotation.Profile;
 
 import demoapp.dom.types.isis.clobs.persistence.IsisClobEntity;
-import lombok.Getter;
 import lombok.NoArgsConstructor;
-import lombok.Setter;
 
 @Profile("demo-jpa")
 //tag::class[]
@@ -57,8 +59,8 @@ public class IsisClobJpa
 
 //end::class[]
     public IsisClobJpa(Clob initialValue) {
-        this.readOnlyProperty = initialValue;
-        this.readWriteProperty = initialValue;
+        setReadOnlyProperty(initialValue);
+        setReadWriteProperty(initialValue);
     }
 
 //tag::class[]
@@ -66,57 +68,79 @@ public class IsisClobJpa
     @GeneratedValue
     private Long id;
 
+
+    @AttributeOverrides({
+            @AttributeOverride(name="name",    column=@Column(name="readOnlyProperty_name")),
+            @AttributeOverride(name="mimeType",column=@Column(name="readOnlyProperty_mimeType")),
+            @AttributeOverride(name="chars",   column=@Column(name="readOnlyProperty_chars"))
+    })
+    @Embedded
+    private ClobJpaEmbeddable readOnlyProperty;
+
     @Title(prepend = "Clob JPA entity: ")
     @PropertyLayout(fieldSetId = "read-only-properties", sequence = "1")
-//    @Persistent(defaultFetchGroup="false", columns = {              // <.>
-//            @Column(name = "readOnlyProperty_name"),
-//            @Column(name = "readOnlyProperty_mimetype"),
-//            @Column(name = "readOnlyProperty_chars"
-//                    , jdbcType = "CLOB"
-//            )
-//    })
-    @Getter @Setter
-    private Clob readOnlyProperty;
+    public Clob getReadOnlyProperty() {
+        return ClobJpaEmbeddable.toClob(readOnlyProperty);
+    }
+
+    public void setReadOnlyProperty(final Clob readOnlyProperty) {
+        this.readOnlyProperty = ClobJpaEmbeddable.fromClob(readOnlyProperty);
+    }
+
+
+    @AttributeOverrides({
+            @AttributeOverride(name="name",    column=@Column(name="readWriteProperty_name")),
+            @AttributeOverride(name="mimeType",column=@Column(name="readWriteProperty_mimeType")),
+            @AttributeOverride(name="chars",   column=@Column(name="readWriteProperty_chars"))
+    })
+    @Embedded
+    private ClobJpaEmbeddable readWriteProperty;
 
     @Property(editing = Editing.ENABLED)                            // <.>
     @PropertyLayout(fieldSetId = "editable-properties", sequence = "1")
-//    @Persistent(defaultFetchGroup="false", columns = {
-//            @Column(name = "readWriteProperty_name"),
-//            @Column(name = "readWriteProperty_mimetype"),
-//            @Column(name = "readWriteProperty_chars"
-//                    , jdbcType = "CLOB"
-//            )
-//    })
-    @Getter @Setter
-    private Clob readWriteProperty;
+    public Clob getReadWriteProperty() {
+        return ClobJpaEmbeddable.toClob(readWriteProperty);
+    }
+
+    public void setReadWriteProperty(final Clob readWriteProperty) {
+        this.readWriteProperty = ClobJpaEmbeddable.fromClob(readWriteProperty);
+    }
+
+
+    @AttributeOverrides({
+            @AttributeOverride(name="name",    column=@Column(name="readOnlyOptionalProperty_name")),
+            @AttributeOverride(name="mimeType",column=@Column(name="readOnlyOptionalProperty_mimeType")),
+            @AttributeOverride(name="chars",   column=@Column(name="readOnlyOptionalProperty_chars"))
+    })
+    @Embedded
+    private ClobJpaEmbeddable readOnlyOptionalProperty;
 
     @Property(optionality = Optionality.OPTIONAL)                   // <.>
     @PropertyLayout(fieldSetId = "optional-properties", sequence = "1")
-//    @Persistent(defaultFetchGroup="false", columns = {
-//            @Column(name = "readOnlyOptionalProperty_name",
-//                    allowsNull = "true"),                           // <.>
-//            @Column(name = "readOnlyOptionalProperty_mimetype",
-//                    allowsNull = "true"),
-//            @Column(name = "readOnlyOptionalProperty_chars"
-//                    , jdbcType = "CLOB"
-//                    , allowsNull = "true")
-//    })
-    @Getter @Setter
-    private Clob readOnlyOptionalProperty;
+    public Clob getReadOnlyOptionalProperty() {
+        return ClobJpaEmbeddable.toClob(readOnlyOptionalProperty);
+    }
+
+    public void setReadOnlyOptionalProperty(final Clob readOnlyOptionalProperty) {
+        this.readOnlyOptionalProperty = ClobJpaEmbeddable.fromClob(readOnlyOptionalProperty);
+    }
+
+    @AttributeOverrides({
+            @AttributeOverride(name="name",    column=@Column(name="readWriteOptionalProperty_name")),
+            @AttributeOverride(name="mimeType",column=@Column(name="readWriteOptionalProperty_mimeType")),
+            @AttributeOverride(name="chars",   column=@Column(name="readWriteOptionalProperty_chars"))
+    })
+    @Embedded
+    private ClobJpaEmbeddable readWriteOptionalProperty;
 
     @Property(editing = Editing.ENABLED, optionality = Optionality.OPTIONAL)
     @PropertyLayout(fieldSetId = "optional-properties", sequence = "2")
-//    @Persistent(defaultFetchGroup="false", columns = {
-//            @Column(name = "readWriteOptionalProperty_name"
-//                    , allowsNull = "true"),                           // <.>
-//            @Column(name = "readWriteOptionalProperty_mimetype"
-//                    , allowsNull = "true"),
-//            @Column(name = "readWriteOptionalProperty_bytes"
-//                    , jdbcType = "CLOB"
-//                    , allowsNull = "true")
-//    })
-    @Getter @Setter
-    private Clob readWriteOptionalProperty;
+    public Clob getReadWriteOptionalProperty() {
+        return ClobJpaEmbeddable.toClob(readWriteOptionalProperty);
+    }
 
+    public void setReadWriteOptionalProperty(final Clob readWriteOptionalProperty) {
+        this.readWriteOptionalProperty = ClobJpaEmbeddable.fromClob(readWriteOptionalProperty);
+    }
 }
 //end::class[]
diff --git a/persistence/jpa/adoc/modules/ROOT/pages/mapping-guide.adoc b/persistence/jpa/adoc/modules/ROOT/pages/mapping-guide.adoc
index 73317e1..786dd58 100644
--- a/persistence/jpa/adoc/modules/ROOT/pages/mapping-guide.adoc
+++ b/persistence/jpa/adoc/modules/ROOT/pages/mapping-guide.adoc
@@ -42,7 +42,8 @@ There are two alternatives:
 
 * manually map the class to an link:https://www.eclipse.org/eclipselink/documentation/3.0/concepts/entities005.htm#BABGBFDG[@Embeddable] class.
 
-The framework provides a number of off-the-shelf `@Embeddable` classes for this purpose; we think it is less boilerplate overall.
+We think the second approach is less boilerplate overall, and is easier to understand what is going on.
+The framework provides an `@Embeddable` classes for each of `Blob` and `Clob`, explained in the sections below.
 
 ==== Blobs
 
@@ -56,14 +57,14 @@ public class MyEntity ... {
     @Embedded
     private BlobJpaEmbeddable pdf;              // <.>
 
-   @Property()
-   @PropertyLayout()
-   public Blob getPdf() {                       // <.>
-       return BlobJpaEmbeddable.to(pod);
-   }
-   public void setPdf(final Blob pdf) {
-       this.pdf = BlobJpaEmbeddable.from(pdf);
-   }
+    @Property()
+    @PropertyLayout()
+    public Blob getPdf() {                      // <.>
+        return BlobJpaEmbeddable.toBlob(pdf);
+    }
+    public void setPdf(final Blob pdf) {
+        this.pdf = BlobJpaEmbeddable.fromBlob(pdf);
+    }
 }
 ----
 
@@ -71,4 +72,33 @@ public class MyEntity ... {
 <.> the property as it is understood by Apache Isis.
 
 
-TIP: if you have multiple instancs of an `@Embedded` type, the `@javax.persistence.AttributeOverrides` and `@javax.persistence.AttributeOverride` provide a standardised way of fine-tuning the column definitions.
\ No newline at end of file
+TIP: if you have multiple instancs of an `@Embedded` type, the `@javax.persistence.AttributeOverrides` and `@javax.persistence.AttributeOverride` provide a standardised way of fine-tuning the column definitions.
+
+==== Clobs
+
+To map a xref:refguide:applib:index/value/Clob.adoc[Clob], use the xref:refguide:persistence:index/jpa/applib/types/ClobJpaEmbedded.adoc[ClobJpaEmbedded] class:
+
+[source]
+.MyEntity.java
+----
+public class MyEntity ... {
+
+    @Embedded
+    private ClobJpaEmbeddable xml;              // <.>
+
+    @Property()
+    @PropertyLayout()
+    public Clob getXml() {                      // <.>
+        return ClobJpaEmbeddable.toClob(xml);
+    }
+    public void setXml(final Clob xml) {
+        this.xml = ClobJpaEmbeddable.fromClob(xml);
+    }
+}
+----
+
+<.> the field as it is persisted by the ORM
+<.> the property as it is understood by Apache Isis.
+
+
+TIP: if you have multiple instances of an `@Embedded` type, the `@javax.persistence.AttributeOverrides` and `@javax.persistence.AttributeOverride` provide a standardised way of fine-tuning the column definitions.
\ No newline at end of file
diff --git a/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/BlobJpaEmbeddable.java b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/BlobJpaEmbeddable.java
index bca7d0e..c5756ab 100644
--- a/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/BlobJpaEmbeddable.java
+++ b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/BlobJpaEmbeddable.java
@@ -22,8 +22,10 @@ package org.apache.isis.persistence.jpa.applib.types;
 import java.util.Arrays;
 import java.util.Optional;
 
+import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Embeddable;
+import javax.persistence.Lob;
 
 import org.apache.isis.applib.value.Blob;
 
@@ -32,18 +34,27 @@ import lombok.Setter;
 import lombok.val;
 
 /**
- * Although JPA supports custom value types, these can only be for simple values; see <a href="https://github.com/eclipse-ee4j/jpa-api/issues/105">eclipse-ee4j/jpa-api/issues/105</a>.
+ * A utility class to enable the persisting of {@link org.apache.isis.applib.value.Blob}s.
  *
  * <p>
- *     EclipseLink <i>does</i> provide its <a href="https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_transformation.htm>Transformation API</a>, but there's a lot of boilerplate involved even so.
+ * Although JPA supports custom value types, these can only be for simple values; see
+ * <a href="https://github.com/eclipse-ee4j/jpa-api/issues/105">eclipse-ee4j/jpa-api/issues/105</a>.
  * </p>
  *
  * <p>
- *     This class provides support for an alternative approach, where the Isis {@link Blob} is marshalled in and out of this class.
+ * EclipseLink <i>does</i> provide its own extension,
+ * <a href="https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_transformation.htm>Transformation API</a>,
+ * but there's a lot of boilerplate involved even so.
+ * </p>
+ *
+ * <p>
+ * This class provides support for an alternative approach, where the Isis {@link Blob} is marshalled in and out of
+ * this class.
  * </p>
  *
  * <p>
  *    Example usage:
+ *
  *     <pre>
  *     &#064;Embedded
  *     private BlobJpaEmbeddable pdf;
@@ -51,10 +62,10 @@ import lombok.val;
  *     &#064;Property()
  *     &#064;PropertyLayout()
  *     public Blob getPdf() {
- *         return BlobJpaEmbeddable.to(pod);
+ *         return BlobJpaEmbeddable.toBlob(pdf);
  *     }
  *     public void setPdf(final Blob pdf) {
- *         this.pdf = BlobJpaEmbeddable.from(pdf);
+ *         this.pdf = BlobJpaEmbeddable.fromBlob(pdf);
  *     }
  *    </pre>
  * </p>
@@ -63,7 +74,7 @@ import lombok.val;
  *     Lastly; note that {@link javax.persistence.AttributeOverrides} and {@link javax.persistence.AttributeOverride}
  *     provide a standardised way of fine-tuning the column definitions.
  * </p>
- * 
+ *
  * @since 2.x {@index}
  */
 @Embeddable
@@ -73,9 +84,9 @@ public final class BlobJpaEmbeddable {
     /**
      * Factory method to marshall a {@link Blob} into a {@link BlobJpaEmbeddable}
      * 
-     * @see #to(BlobJpaEmbeddable) 
+     * @see #toBlob(BlobJpaEmbeddable)
      */
-    public static BlobJpaEmbeddable from(Blob blob) {
+    public static BlobJpaEmbeddable fromBlob(Blob blob) {
         if(blob == null) {
             return null;
         }
@@ -89,29 +100,31 @@ public final class BlobJpaEmbeddable {
     /**
      * Reciprocal method to marshall a {@link BlobJpaEmbeddable} into a {@link Blob}
      * 
-     * @see #from(Blob)
+     * @see #fromBlob(Blob)
      */
-    public static Blob to(final BlobJpaEmbeddable pod) {
-        return Optional.ofNullable(pod).map(BlobJpaEmbeddable::toBlob).orElse(null);
+    public static Blob toBlob(final BlobJpaEmbeddable blobJpaEmbeddable) {
+        return Optional.ofNullable(blobJpaEmbeddable).map(BlobJpaEmbeddable::asBlob).orElse(null);
     }
 
     @Column(nullable = false, length = 255)
     private String mimeType;
 
     @Column(nullable = false)
+    @Lob
+    @Basic
     private byte[] bytes;
 
     @Column(nullable = false, length = 255)
     private String name;
 
-    public Blob toBlob() {
+    public Blob asBlob() {
         return new Blob(name, mimeType, bytes);
     }
 
     
     @Override
     public String toString() {
-        return toBlob().toString();
+        return asBlob().toString();
     }
 
     @Override
diff --git a/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/BlobJpaEmbeddable.java b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/ClobJpaEmbeddable.java
similarity index 55%
copy from persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/BlobJpaEmbeddable.java
copy to persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/ClobJpaEmbeddable.java
index bca7d0e..9dee3b6 100644
--- a/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/BlobJpaEmbeddable.java
+++ b/persistence/jpa/applib/src/main/java/org/apache/isis/persistence/jpa/applib/types/ClobJpaEmbeddable.java
@@ -19,42 +19,52 @@
 
 package org.apache.isis.persistence.jpa.applib.types;
 
-import java.util.Arrays;
+import java.util.Objects;
 import java.util.Optional;
 
+import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Embeddable;
+import javax.persistence.Lob;
 
-import org.apache.isis.applib.value.Blob;
+import org.apache.isis.applib.value.Clob;
 
 import lombok.Getter;
 import lombok.Setter;
 import lombok.val;
 
 /**
- * Although JPA supports custom value types, these can only be for simple values; see <a href="https://github.com/eclipse-ee4j/jpa-api/issues/105">eclipse-ee4j/jpa-api/issues/105</a>.
+ * A utility class to enable the persisting of {@link org.apache.isis.applib.value.Clob}s.
  *
  * <p>
- *     EclipseLink <i>does</i> provide its <a href="https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_transformation.htm>Transformation API</a>, but there's a lot of boilerplate involved even so.
+ * Although JPA supports custom value types, these can only be for simple values;
+ * see <a href="https://github.com/eclipse-ee4j/jpa-api/issues/105">eclipse-ee4j/jpa-api/issues/105</a>.
  * </p>
  *
  * <p>
- *     This class provides support for an alternative approach, where the Isis {@link Blob} is marshalled in and out of this class.
+ * EclipseLink <i>does</i> provide its own extension,
+ * <a href="https://www.eclipse.org/eclipselink/documentation/2.5/jpa/extensions/a_transformation.htm>Transformation API</a>,
+ * but there's a lot of boilerplate involved even so.
+ * </p>
+ *
+ * <p>
+ * This class provides support for an alternative approach, where the Isis {@link Clob} is marshalled in and out of
+ * this class.
  * </p>
  *
  * <p>
  *    Example usage:
  *     <pre>
  *     &#064;Embedded
- *     private BlobJpaEmbeddable pdf;
+ *     private ClobJpaEmbeddable xml;
  *
  *     &#064;Property()
  *     &#064;PropertyLayout()
- *     public Blob getPdf() {
- *         return BlobJpaEmbeddable.to(pod);
+ *     public Clob getXml() {
+ *         return ClobJpaEmbeddable.toClob(xml);
  *     }
- *     public void setPdf(final Blob pdf) {
- *         this.pdf = BlobJpaEmbeddable.from(pdf);
+ *     public void setPdf(final Clob xml) {
+ *         this.xml = ClobJpaEmbeddable.fromClob(xml);
  *     }
  *    </pre>
  * </p>
@@ -68,50 +78,52 @@ import lombok.val;
  */
 @Embeddable
 @Getter @Setter
-public final class BlobJpaEmbeddable {
+public final class ClobJpaEmbeddable {
 
     /**
-     * Factory method to marshall a {@link Blob} into a {@link BlobJpaEmbeddable}
+     * Factory method to marshall a {@link Clob} into a {@link ClobJpaEmbeddable}
      * 
-     * @see #to(BlobJpaEmbeddable) 
+     * @see #toClob(ClobJpaEmbeddable)
      */
-    public static BlobJpaEmbeddable from(Blob blob) {
-        if(blob == null) {
+    public static ClobJpaEmbeddable fromClob(Clob clob) {
+        if(clob == null) {
             return null;
         }
-        val blobJpaEmbeddable = new BlobJpaEmbeddable();
-        blobJpaEmbeddable.bytes = blob.getBytes();
-        blobJpaEmbeddable.mimeType = blob.getMimeType().toString();
-        blobJpaEmbeddable.name = blob.getName();
-        return blobJpaEmbeddable;
+        val clobJpaEmbeddable = new ClobJpaEmbeddable();
+        clobJpaEmbeddable.chars = clob.getChars().toString();
+        clobJpaEmbeddable.mimeType = clob.getMimeType().toString();
+        clobJpaEmbeddable.name = clob.getName();
+        return clobJpaEmbeddable;
     }
 
     /**
-     * Reciprocal method to marshall a {@link BlobJpaEmbeddable} into a {@link Blob}
-     * 
-     * @see #from(Blob)
+     * Reciprocal method to marshall a {@link ClobJpaEmbeddable} into a {@link Clob}
+     *
+     * @see #fromClob(Clob)
      */
-    public static Blob to(final BlobJpaEmbeddable pod) {
-        return Optional.ofNullable(pod).map(BlobJpaEmbeddable::toBlob).orElse(null);
+    public static Clob toClob(final ClobJpaEmbeddable clobJpaEmbeddable) {
+        return Optional.ofNullable(clobJpaEmbeddable).map(ClobJpaEmbeddable::asClob).orElse(null);
     }
 
     @Column(nullable = false, length = 255)
     private String mimeType;
 
     @Column(nullable = false)
-    private byte[] bytes;
+    @Lob
+    @Basic
+    private String chars;
 
     @Column(nullable = false, length = 255)
     private String name;
 
-    public Blob toBlob() {
-        return new Blob(name, mimeType, bytes);
+    public Clob asClob() {
+        return new Clob(name, mimeType, chars);
     }
 
     
     @Override
     public String toString() {
-        return toBlob().toString();
+        return asClob().toString();
     }
 
     @Override
@@ -121,18 +133,18 @@ public final class BlobJpaEmbeddable {
         if (o == null || getClass() != o.getClass())
             return false;
 
-        final BlobJpaEmbeddable that = (BlobJpaEmbeddable) o;
+        final ClobJpaEmbeddable that = (ClobJpaEmbeddable) o;
 
         if (mimeType != null ? !mimeType.equals(that.mimeType) : that.mimeType != null)
             return false;
-        if (!Arrays.equals(bytes, that.bytes))
+        if (!Objects.equals(chars, that.chars))
             return false;
         return name != null ? name.equals(that.name) : that.name == null;
     }
 
     @Override public int hashCode() {
         int result = mimeType != null ? mimeType.hashCode() : 0;
-        result = 31 * result + Arrays.hashCode(bytes);
+        result = 31 * result + Objects.hashCode(chars);
         result = 31 * result + (name != null ? name.hashCode() : 0);
         return result;
     }