Saturday, April 20, 2024
HomeJavaThe best way to map composite column varieties with Hibernate

The best way to map composite column varieties with Hibernate


When most builders design their desk and entity fashions, they create tables that solely use fundamental column varieties and map these to fundamental entity attributes. Although these are probably the most generally used varieties, they don’t seem to be the one ones supported by fashionable relational databases and Hibernate. You may as well use composite, JSON, and XML varieties. I already confirmed you tips on how to map a JSON column utilizing totally different Hibernate variations. On this article, I need to deal with mapping composite column varieties. Since Hibernate 6.2, this received extremely easy if you happen to’re utilizing an Oracle, PostgreSQL, or DB2 database.

A composite kind represents a construction that consists of a number of fields. Every subject has a reputation and might retailer a worth. Right here you’ll be able to see an instance of such a kind definition for a PostgreSQL database.

create kind my_struct as (longProp bigint, stringProp varchar(255))

I’ll use the my_struct kind within the examples of this text. It incorporates the longProp subject, which shops a numerical worth, and the stringProp subject, which shops textual content. When creating your database desk, you need to use this sort like some other column kind.

create desk MyEntity (
	id bigint not null,
	structProperty my_struct,
	major key (id)
)

Beginning with Hibernate 6.2, you’ll be able to simply map a composite kind column to an embeddable, which you’ll then use as your entity attribute kind.

Mapping composite varieties with Hibernate 6.2

A composite kind consists of a number of fields. When mapping it to an entity attribute, you clearly need to map it to an attribute kind that handles every subject individually. That makes an embeddable an apparent selection.

As I confirmed in a latest article, you’ll be able to mannequin an embeddable as a Java class or file. You’ll be able to map each of them to a composite kind. However the way you outline your embeddable has a small affect on Hibernate’s mapping.

Mapping an embeddable class or file to a composite kind

The best strategy to map an embeddable to a composite kind is to annotate your class with a @Struct annotation and reference the title of the composite kind. This works in the identical manner for embeddable carried out as a category or as a file.

@Embeddable
@Struct(title = "my_struct")
public class MyStructure {

	personal String stringProp;
	
	personal Lengthy longProp;

	...
}
@Embeddable
@Struct(title = "my_struct")
public file MyStructureRecord(String stringProp, Lengthy longProp) {}

Since model 6.2, Hibernate helps information as embeddable by default. In the event you’re utilizing Hibernate 6.0 or 6.1, you must implement an EmbeddableInstantiator, which tells Hibernate tips on how to instantiate the file.

Within the following examples, I’ll use the embeddable class MyStructure. However you can use the embeddable file MyStructureRecord in the identical manner.

After implementing your embeddable and defining the mapping to a composite kind, you need to use it like some other embeddable.

@Entity
public class MyEntity {

	@Id
	@GeneratedValue
	personal Lengthy id;

	@Embedded
	personal MyStructure structProperty;
	
	...
}

You solely see a distinction while you verify your desk mannequin or the executed SQL statements. As a substitute of mapping every attribute of your embeddable to a separate database column, Hibernate maps every attribute to a subject of the referenced composite kind.

MyStructure p = new MyStructure();
p.setLongProp(123L);
p.setStringProp("abc");

MyEntity e = new MyEntity();
e.setStructProperty(p);
em.persist(e);
11:43:52,494 DEBUG [org.hibernate.SQL] - 
    choose
        nextval('MyEntity_SEQ')
11:43:52,510 DEBUG [org.hibernate.SQL] - 
    insert 
    into
        MyEntity
        (structProperty,id) 
    values
        (?,?)
11:43:52,510 TRACE [org.hibernate.orm.jdbc.bind] - binding parameter [1] as [STRUCT] - [[email protected]]
11:43:52,514 TRACE [org.hibernate.orm.jdbc.bind] - binding parameter [2] as [BIGINT] - [1]

You’ll be able to even use the embeddable in your JPQL queries. Like a traditional embeddable, you employ the trail operator “.” to navigate out of your entity to the embeddable and from there to a particular attribute.

MyEntity e = em.createQuery("""
								SELECT e 
								FROM MyEntity e 
								WHERE e.structProperty.longProp = 456""", 
							MyEntity.class)
				.getSingleResult();

Hibernate interprets this into the SQL dialect of your database. I’m utilizing a PostgreSQL database for this instance, and Hibernate generates the next assertion.

16:06:43,917 DEBUG [org.hibernate.SQL] - 
    choose
        m1_0.id,
        (m1_0.structProperty).longProp,
        (m1_0.structProperty).stringProp 
    from
        MyEntity m1_0 
    the place
        (
            m1_0.structProperty
        ).longProp=456

Adjusting the order of the composite’s fields

Whenever you use the default mapping, you may run into the issue that the order wherein Hibernate maps the attributes of your embeddable doesn’t match the construction of your composite kind. The explanation for that downside turns into apparent while you take a look at the information construction saved in a composite kind. It’s a easy record of values. The order of the record’s parts has to match the order wherein the fields of the composite kind are outlined.

So, for the next definition of the my_struct kind, Hibernate wants to supply the worth of the stringProp attribute as the first and the worth of the longProp attribute because the 2nd worth in that record.

create kind my_struct as (stringProp varchar(255), longProp bigint)

Hibernate’s default order is determined by the way you implement your embeddable. In the event you implement an embeddable class, Hibernate maps the attributes within the alphabetical order of their names. In the event you implement it as a file, Hibernate maps the fields within the order listed within the file definition.

You’ll be able to modify the default mapping by specifying the order wherein Hibernate shall map the attributes. You try this by offering an array of attribute names to the @Struct annotation. Hibernate then maps the attributes of your embeddable class or file within the order outlined by the attributes array.

@Embeddable
@Struct(title = "my_struct", attributes = {"stringProp", "longProp"})
public class MyStructure {

	personal String stringProp;
	
	personal Lengthy longProp;

	...
}

Conclusion

The @Struct annotation launched in Hibernate 6.2 lets you map an embeddable to a composite column kind. As you noticed within the examples, the mapping is simple. However it’s good to be certain that Hibernate maps the weather of the embeddable in the identical order because the composite kind outlined its fields.

After you might have carried out your embeddable and outlined the mapping to the composite kind, you need to use it in the identical manner as some other embeddable. This even contains your JPQL queries. You should use the trail operator “.” to navigate from an entity object by way of the embeddable attribute to a particular subject.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments