JPA & Hibernate: Basic Annotations You Need To Know

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
When you start learning and using Hibernate and JPA, the number of annotations might be overwhelming. But as long as you rely on the defaults, you can implement your persistence layer using only a small subset of them. After you have mastered the basic annotations, you can take a look at additional customization options. You can, for example, customize the join tables of many-to-many associations, use composite primary keys, or share a primary key value between 2 associated entities. But please be careful with any mapping that tries to handle a significant difference between your table model and your domain model. quite often, the simpler mappings are better than the complex ones. They provide better performance and are much easier to understand by all developers in your team. Hi, I’m Thorben Janssen from thoughts-on-java.org and in this video I will show you the key annotations you need to know to use JPA and Hibernate. But before we proceed, if you are new here and want to learn how to build incredible efficient persistence layers with JPA and Hibernate and all types of other Java persistence related stuff, start now by subscribing and clicking the bell, so you don't miss anything. You only need the more advanced mappings if you need to map a legacy database or use various kinds of performance optimizations. But especially when you are new to JPA and Hibernate, you should ignore these features and focus on the basic concepts. So, let’s take a look at the most important annotations and their attributes. For each annotation, I will explain which attributes you really need and which ones you should better avoid. And if you want to dive deeper into JPA and make sure you have a solid understanding of all the basic concepts, I recommend enrolling in my JPA for Beginners online course. JPA entities don’t need to implement any interface or extend a superclass. They are simple POJOs. But you still need to identify a class as an entity class, and you might want to adapt the default table mapping. The JPA specification requires the @Entity annotation. It identifies a class as an entity class. You can use the name attribute of the @Entity annotation to define the name of the entity. It has to be unique for the persistence unit, and you use it to reference the entity in your JPQL queries. By default, each entity class maps a database table with the same name in the default schema of your database. You can customize this mapping using the name, schema, and catalog attributes of the @Table annotation. The name attribute enables you to change the name of the database table which your entity maps. The schema attribute specifies the name of the database schema in which the table is located. And the catalog attribute describes the name of the database catalog that stores the metadata information of the table. The @Table annotation also defines 2 attributes that enable you to influence the generation of the database table. These are called indexes and uniqueConstraints. I don’t recommend to use them. External script and tools like Liquibase or Flyway are a much better option to create and update your database. By default, all JPA implementations map each entity attribute to a database column with the same name and a compatible type. The following annotations enable you to perform basic customizations of these mappings. You can, for example, change the name of the column, adapt the type mapping, identify primary key attributes, and generate unique values for them. Let’s start with the @Column annotation. It is an optional annotation that enables you to customize the mapping between the entity attribute and the database column. You can use the name attribute to specify the name of the database column which the entity attribute maps The attributes updatable and insertable enable you to exclude the attribute from insert or update statements. You should only use the table attribute if you map your entity to 2 database tables. In general, I don’t recommend to use this mapping. But you sometimes need it to work with a legacy database or as a temporary step during a complex refactoring. All other attributes only affect the generated CREATE TABLE statement, and I don’t recommend to use them. These are: The columnDefinition attribute that allows you to define an SQL fragment that’s used during table definition. The length attribute, which defines the length of String-valued database column. The attributes scale and precision, which specify the scale and precision of a decimal value The unique attribute that defines a unique constraint on the mapped column. JPA and Hibernate require you to specify at least one primary key attribute for each entity. You can do that by annotating an attribute with the @Id annotation. When we’re talking about primary keys, we also need to talk about sequences and auto-incremented database columns. These are the 2 most common database features to generate unique primary key values. If you annotate your primary key attribute with the @GeneratedValue annotation, you can use a database sequence by setting the strategy attribute to GenerationType.SEQUENCE. Or, if you want to use an auto-incremented database column to generate your primary key values, you need to set the strategy to GenerationType.IDENTITY. The generator attribute of the @GeneratedValue annotation enables you to reference a custom generator. You can use it to customize a standard generator, for example to use a custom database sequence, or to implement your own generator. I explain the primary key generation strategies and their performance impacts in more detail in How to generate primary keys with JPA and Hibernate. I will put the link to it in the description box and here The @Enumerated annotation enables you to define how an enum attribute gets persisted in the database. By default, all JPA implementations map the ordinal value of the enum to a numeric database column. As I explained in more detail in my guide on enum mappings, the ordinal makes it hard to add or remove values to the enum. The mappingas a String is more robust and much easier to read. You can activate this mapping by EnumType.STRING to the @Enumerated annotation. If you’re still using java.util.Date or java.util.Calendar as your attribute types, you need to annotate the attribute with @Temporal. Using this annotation, you can define if the attribute shall be mapped as an SQL DATE, TIME, or TIMESTAMP. This mapping works really well, but I recommend using the classes of the Date and Time API instead. These classes are much easier to use in your business code, and they provide all the required mapping information. That means that they don’t require any annotations. In Java, there is almost no limit to the size of a String or a byte array. But that’s not the case for relational databases. They provide specific data types for large objects. These are BLOB for binary large objects and CLOB for character large objects. Using JPA’s @Lob annotation, you can map a BLOB to a byte array and a CLOB to a String. Your persistence provider then fetches the whole BLOB or CLOB when it initializes the entity attribute. In addition to that, Hibernate also supports mappings to java.sql.Blob and java.sql.Clob. These are not as easy to use a byte array or a String, but they can provide better performance. I explained that mapping in great detail in Mapping BLOBs and CLOBs with Hibernate and JPA. You can also map associations between your entities. In the table model, these are modeled as foreign key columns. These associations are mapped as attributes of the type of the associated entity or a Collection of associated entities, in your domain model. In both cases, you need to describe the association mapping. You can do that using a @ManyToMany, @ManyToOne, @OneToMany, or @OneToOne annotation. Many-to-many associations are very common in relational table models. A typical example is an association between books and authors. In your domain model, you can map this association in a uni- or bidirectional way using attributes of type List, Set or Map, and a @ManyToManyannotations. Here you can see a typical example of the owning side of the association. You can use it to model a unidirectional many-to-many association. Or you can use it as the owning side of a bidirectional mapping. In both cases, Hibernate uses an association table that contains foreign key columns that reference both ends of the association. When you’re using this annotation, you should also be familiar with JPA’s FetchTypes. The fetch attribute of the @ManyToMany annotation allows you to define the FetchType that shall be used for this association. The FetchType defines when the persistence provider fetches the referenced entities from the database. By default, a many-to-many association uses the FetchType.LAZY. This tells your persistence provider to fetch the associated entities when you use them. That’s the most efficient approach, and you shouldn’t change it. By setting the cascade attribute, you can also tell your persistence provider which entity operations it shall cascade to all associated entities. This can make working with graphs of entities much easier. But you should avoid CascadeType.REMOVE for all many-to-many associations. It removes much more data than you would expect. and If you want to model the association in a bidirectional way, you need to implement a similar mapping on the referenced entity. But this time, you also need to set the mappedBy attribute of the @ManyToMany annotation to the name of the attribute that owns the association. To your persistence provider, this identifies the mapping as a bidirectional one. You use the same @ManyToMany annotation to define the referencing side of the association, as you use to specify the owning side of it. So, you can use the same cascade and fetch attributes, as I described before. Let's take a look at Many-to-one and one-to-many associations next. They represent the same association from 2 different perspectives. So, it’s no surprise that you can use them together to define a bidirectional association. You can also use each of them on their own to create a unidirectional many-to-one or one-to-many association. But you should avoid unidirectional one-to-many associations. Hibernate handles them very inefficient. Let’s start with @ManyToOne annotation. It defines the owning side of a bidirectional many-to-one/one-to-many association. You do that on the entity that maps the database table that contains the foreign key column. When you’re using a @ManyToOne annotation, you should be familiar with its fetch and cascade attributes. The fetch attribute enables you to define the FetchType that shall be used for this association. You can set the cascade attribute to define which operations on this entity shall get cascaded to all associated entities. That gets often used to cascade an operation from a parent to a child entity. So, it’s mostly used on a @OneToMany association, and I will show it in the next section. You can also set the optional attribute to false to indicate that this association is mandatory. You can use the @OneToMany annotation to define the referencing side of a bidirectional many-to-one/one-to-many association. As explained before, you shouldn’t use it to model a unidirectional one-to-many Hibernate handles these associations very inefficiently. Similar to the referencing side of a bidirectional many-to-many association, you can reference the name of the attribute that owns the association in the mappedBy attribute. That tells your persistence provider that this is the referencing side of a bidirectional association, and it reuses the association mapping defined by the owning side. I already explained the fetch and cascade attributes for the @ManyToMany and @ManyToOne annotations. You can use them in the same way with the @OneToMany annotation. In addition to these 2 attributes, you should also know the orphanRemoval attribute. If you set it to true, Hibernate removes an entity from the database when it gets removed from the association. That’s often used for parent-child associations in which the child can’t exist without its parent. A typical example would be the item of an order. The item can’t exist without the order. So, it makes sense to remove it as soon as the association to the order gets removed. One-to-one associations are only rarely used in relational table models. You can map them using a @OneToOne annotation. Similar to the previously discussed association mapping, you can model a uni- or bidirectional one-to-one associations. The attribute that’s defined on the entity that maps the database table that contains the foreign key column owns the association. The @OneToOne annotation supports the fetch, cascade, and optional attributes that I already explained in the previous sections. And if you model it as a bidirectional association, you need to set the mappedBy attribute of the referencing side of the association to the attribute name that owns the association. As you have seen, you only need a relatively small number of annotations to define your domain model. In most cases, you only need to annotate your entity class with @Entity and your primary key attribute with @Id and @GeneratedValue. If the names of your entity class or one of its attributes don’t match the table or column names, you can adjust the mapping using a @Table or @Column annotation. You can also change the type mappings using an @Enumerated, @Temporal, or @Lob annotation. One of the key features of any object-relational mapper is the handling of associations. With JPA and Hibernate, you can map one-to-one, one-to-many, many-to-one, and many-to-many associations in a uni- or bidirectional way. All association mappings require an additional annotation that describes the association mapping and that you can use to define the fetching and cascading behavior of it. OK, that’s it for today. If you want to learn more about Hibernate, you should join the free Thoughts on Java Library. It gives you free access to a lot of member-only content like a cheat for this video and an ebook about using native queries with JPA and Hibernate. I’ll add the link to it to the video description below. And if you like today’s video, please give it a thumbs up and subscribe below. Bye
Info
Channel: Thorben Janssen
Views: 13,309
Rating: undefined out of 5
Keywords: Hibernate, JPA, How to, Tutorial, Beginners, Java, Getting Started, JPQL, Queries, JPQL queries, hibernate, performance, tuning, basic annotations, POJO, @Entity, BLOB, CLOB, java.sql.Blob, java.sql.Clob, @ManyToOne, @OneToMany, FetchType.LAZY, Thorben
Id: GKIXI_Vc28k
Channel Id: undefined
Length: 15min 11sec (911 seconds)
Published: Thu May 14 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.