Mapping BLOBs & CLOBs with JPA and Hibernate

Mapping BLOBs & CLOBs with JPA and Hibernate


Mapping BLOBs & CLOBs with JPA and Hibernate

Today I will show you how to map BLOBs and CLOBs with JPA and Hibernate. You will learn how to map these database columns to a String or a byte[] and how to use the java.sql classes Blob and Clob. And at the end of this video, I will show you an easy and portable way to load your BLOBs and CLOBs lazily.

Especially the lazy-loading trick is a mapping that most developers are surprised about and that I have used with great success in various client projects.
But before we start, if this is your first time here, and you want to learn how to create your entity mappings with ease, build incredible efficient persistence layers with Hibernate and all types of other Java persistence related stuff, start now by subscribing and clicking the bell, so you don’t miss anything.

Databases use the data types binary large object aka BLOB and character large object aka CLOB to store large objects, like images and very long texts. JPA and Hibernate provide two kinds of mappings for these types.

You can choose if you want to:

Materialize the LOB and map it to a byte[] or a String. This mapping is defined by the JPA specification and prioritizes ease of use over performance.

Or you can use JDBC’s LOB locators java.sql.Blob and java.sql.Clob. The LOB locators enable your JDBC driver to optimize for performance, e.g., by streaming the data. This mapping is Hibernate-specific.


If you like this video, please give me your thumbs up and share it with your friends and co-workers.

Like my channel? Subscribe!
http://bit.ly/2cUsid8

Join the free Member Library:
https://goo.gl/dtyIIC

Read the accompanying post: https://thoughts-on-java.org/mapping-

Want to connect with me?
Blog: http://www.thoughts-on-java.org/
Twitter: https://twitter.com/thjanssen123
Facebook: https://www.facebook.com/thoughtsonjava

#JPA #Hibernate #blob #clob


Content

1.09 -> Hi, I'm Thorben Janssen from thoughts-on-java.org.
4.67 -> Today I will show you how to map BLOBs and CLOBs with JPA and Hibernate.
9.37 -> You will learn how to map these database columns to a String or a byte[] and how
14.82 -> to use the java.sql classes Blob and Clob.
18.86 -> And at the end of this video, I will show you an easy and portable way to
22.55 -> load your BLOBs and CLOBs lazily.
25.01 -> Especially the lazy-loading trick is a mapping that most developers are
29.08 -> surprised about and that I have used with great success in various client
33.41 -> projects.
34.82 -> But before we start, if this is your first time here, and you want to learn
38.42 -> how to create your entity mappings with ease, build incredible efficient
42.219 -> persistence layers with Hibernate and all types of other Java persistence
46.059 -> related stuff, start now by subscribing and clicking the bell, so you don't miss
50.54 -> anything.
51.55 -> OK, let's dive into today's topic.
55.26 -> Databases use the data types binary large object aka BLOB and character
60.949 -> large object aka CLOB to store large objects, like images and very long
66.52 -> texts.
67.52 -> JPA and Hibernate provide two kinds of mappings for these types.
72.039 -> You can choose if you want to: Materialize the LOB and map it to a
77.06 -> byte[] or a String.
78.939 -> This mapping is defined by the JPA specification and prioritizes ease of
82.99 -> use over performance.
85.43 -> Or you can use JDBC’s LOB locators java.sql.Blob and java.sql.Clob.
90.84 -> The LOB locators enable your JDBC driver to optimize for performance, e.g., by
96.799 -> streaming the data.
98.639 -> This mapping is Hibernate-specific.
101.319 -> The mapping of both approaches looks almost identical.
104.539 -> You just need to annotate your entity attribute with a @Lob annotation.
109.02 -> The only difference is the type of your entity attribute.
112.479 -> But you will see a huge difference in the way you use the values of these
116.28 -> entity attributes.
117.829 -> Let’s use both options to map the following Book table.
122.549 -> The columns cover of type oid and content of type text are the important
128.039 -> ones for this video.
129.179 -> We will map the cover column as BLOB and the content column as a CLOB.
135.469 -> The materialized mapping to a String or a byte[] is the most intuitive mapping
140.25 -> for most Java developers.
142.68 -> Entity attributes of these types are easy to use, and it feels natural to use
146.97 -> them in your domain model.
149.09 -> But Hibernate also needs to fetch all data stored in the LOB immediately and
153.56 -> map it to a Java object.
156.28 -> Depending on the size of your LOB, this can cause severe performance problems.
160.31 -> If you, e.g., store large video files in your database, it’s often better to
164.659 -> use JDBC’s LOB locators.
166.92 -> I show you how to use them in the next section.
170.45 -> The JPA specification defines this mapping.
173.42 -> You can not only use it with Hibernate but also with EclipseLink and OpenJPA.
181.36 -> Creating materialized mappings is very simple.
184.019 -> You just need an attribute of type String or byte[] and annotate it with
188.019 -> JPA’s @Lob annotation.
190.709 -> Hibernate can also map nationalized character data types, like NCHAR,
194.59 -> NVARCHAR, LONGNVARCHAR, and NCLOB.
198.209 -> To define such a mapping, you need to annotate your entity attribute of type
201.78 -> String with Hibernate’s @Nationalized annotation instead of @Lob.
206.719 -> As I said at the beginning of this video, materialized mappings are
209.89 -> straightforward to use.
212.05 -> Hibernate fetches all data stored in the LOB when it initializes the entity and
216.319 -> maps it to a String or byte[].
218.959 -> You can then use the entity attribute in the same way as any other attribute.
222.939 -> Here are 2 examples that store a new Book entity and fetch an existing Book
228.12 -> entity from the database.
233.209 -> With Hibernate, you can use the same approach to map your LOB to a
237.079 -> java.sql.Clob or a java.sql.Blob.
240.239 -> These Java types are not as easy to use as a String or byte[].
244.609 -> But they enable your JDBC driver to use LOB-specific optimizations, which might
249.76 -> improve the performance of your application.
252.2 -> If and what kind of optimizations are used, depends on the JDBC driver and
257.1 -> your database.
258.8 -> The mapping is Hibernate-specific and not defined by the JPA specification.
266.479 -> As you can see in the following code snippet, the mapping to JDBC’s LOB
269.95 -> locators java.sql.Clob and java.sql.Blob is almost identical to the previous
276.039 -> example.
277.11 -> The only 2 differences are: The cover attribute is now of type Blob.
281.99 -> The content attribute is of type Clob.
284.68 -> And Hibernate also enables you to map the nationalized character data types
288.93 -> NCHAR, NVARCHAR, LONGNVARCHAR, and NCLOB to a java.sql.Clob.
295.67 -> The types java.sql.Clob and java.sql.Blob provide more flexibility
300.12 -> to the JDBC driver, but they are not as easy to use as a byte[] or a String.
305.75 -> You need to use Hibernate’s BlobProxy and ClobProxy classes to create a Blob
310.59 -> or Clob.
311.87 -> As you can see in the code, that’s a rather small inconvenience.
315.86 -> To create a Blob object, you can call the generateProxy method of the
320.34 -> BlobProxy with a byte[] or an InputStream.
323.87 -> And you can call the generateProxy method of the ClobProxy with a String or
328.199 -> a Reader.
329.389 -> That makes both proxies very comfortable to use.
333.139 -> Reading a Blob or a Clob is also not too complicated but requires a little more
337.639 -> work than using a byte[] or a String.
340.59 -> The java.sql.Blob interface provides you with multiple methods to get an
344.77 -> InputStream or a byte[] of the BLOB value.
348.72 -> And the java.sql.Clob interface defines various ways to get a Reader or a String
353.8 -> of the CLOB value.
358.879 -> When we are talking about LOBs, we also need to talk about lazy loading.
362.86 -> In most cases, LOBs require too much memory to fetch them eagerly every time
367.3 -> you fetch the entity.
369.05 -> It would be better only to fetch the LOB if you need it in your business code.
373.46 -> As I explained in a previous video, JPA defines lazy fetching for basic
377.27 -> attributes as a hint.
379.319 -> That means that your persistence provider can decide if it follows that
382.69 -> hint or fetches the value eagerly.
386.21 -> As a result, the support and implementation of this feature depend on
390.28 -> your JPA implementation.
391.93 -> Hibernate, for example, requires you to activate byte code enhancement.
396.389 -> I explain that in more details in my Hibernate Performance Tuning Online
399.91 -> Training.
401.19 -> In this video, I want to show and recommend a different approach.
404.91 -> It doesn’t require any provider-specific features and works
408.28 -> with all JPA implementations.
411.879 -> The easiest and best way to load LOBs lazily is to store them in a separate
415.91 -> table.
416.91 -> You can then map the LOBs to a separate entity.
420.36 -> That allows you to remove the LOBs from the Book entity and to model a
424.78 -> unidirectional one-to-one association with a shared primary key on the
428.47 -> BookLobs entity.
433.33 -> The mapping of the 2 entities is pretty simple.
436.75 -> After removing the 2 LOBs, the Book entity is a simple entity with a
440.56 -> generated primary key and a title attribute.
443.97 -> As I will show you in the next section, you don’t need to model the
447.06 -> association to the BookLob entity.
450.159 -> The BookLob entity models a unidirectional one-to-one association to
454.919 -> the Book entity.
456.689 -> The @MapsId annotation tells Hibernate to use the primary key value of the
460.789 -> associated Book.
462.189 -> I explained that in more details in Hibernate Tips: How to Share the
466.069 -> Primary Key in a One-to-One Association.
469.38 -> And the materialized mappings of the content and cover attributes are the
473.569 -> same as I used in the first example.
476.19 -> The shared primary key and the unidirectional one-to-one associations
480.039 -> make using the 2 entities very easy.
482.919 -> To store a new book in your database, you need to instantiate and persist a
487.08 -> Book and BookLobs entity.
489.81 -> The BookLobs entity uses the primary key value of the associated Book entity.
494.159 -> So, you need to make sure to initialize the association before you persist the
498.78 -> BookLobs entity.
501.25 -> And when you want to get the BookLobs entity for a given Book entity, you just
505.78 -> need to call the find method on your EntityManager with the id of the Book.
510.979 -> As you have seen, JPA provides an easy way to map LOBs to entity attributes of
518.1 -> type byte[] and String.
520.6 -> This mapping is not only easy to define, but it’s also very comfortable to use
524.82 -> and feels natural to most Java developers.
528 -> The only downside of it is that it prevents your JDBC driver from using
531.97 -> LOB-specific optimizations.
534.97 -> Hibernate takes the mapping of LOBs one step further.
538.14 -> In addition to the JPA mappings, it also allows you to map LOBs to JDBC’s Clob
543.63 -> and Lob locators.
545.37 -> These mappings are a little bit harder to use.
547.96 -> But they enable your JDBC driver to implement LOB specific implementations,
552.58 -> like the streaming of large objects.
554.97 -> That can provide better performance if you’re using a lot of or very huge
558.91 -> LOBs.
559.91 -> OK, that’s it for today.
562.06 -> If you want to learn more about Hibernate, you should join the free
564.6 -> Thoughts on Java Library.
566.4 -> It gives you free access to a lot of member-only content like a cheat for
570.03 -> this video and an ebook about using native queries with JPA and Hibernate.
574.841 -> I’ll add the link to it to the video description below.
577.56 -> And if you like today’s video, please give it a thumbs up and subscribe below.

Source: https://www.youtube.com/watch?v=uZXfZZ59cjU