What impact does the #embedded annotation mean? - java

How does the Embedded annotation affect the database?
How will SQL queries need to change?
What's the typical usecase for using the annotation?

How does Embedded annotation affect the database?
It does not affect it at all. On ORM provider layer all fields from embedded entity are merged with parent entity and treated the same as if they were declared there all the time. In other words it works as if you would literally copy all the fields, getters and setters into the entity that contains embedded object.
How will SQL queries need to change?
They won't. You don't need to change anything. See above.
What's the typical case for using the annotation annotation?
Sometimes you have a huge table with several columns (especially with legacy databases). However some columns are logically tied to each other (like street, city and phone number in CUSTOMER table). When you don't want to create an object with all the fields, you create an embedded Address object. This way you logically group address columns into an object instead of having equally huge POJO with a flat list of fields.
Using embedded objects is considered a good practice, especially when strong 1-1 relationship is discovered.

extending the answer of #Tomasz Nurkiewicz Embedded objects are useful to mapping a table's with a composite primary key whit help of the annotation #EmbenddedId

What's the typical usecase for using the annotation?
This is typically to represent a composite primary key as an embeddable class:
#Entity
public class Project {
#EmbeddedId ProjectId id;
:
}
#Embeddable
Class ProjectId {
int departmentId;
long projectId;
}
The primary key fields are defined in an embeddable class. The entity contains a single primary key field that is annotated with #EmbeddedId and contains an instance of that embeddable class. When using this form a separate ID class is not defined because the embeddable class itself can represent complete primary key values.
How does the Embedded annotation affect the database?
It does not. Use this annotation to represent a composite primary key.
How will SQL queries need to change?
They won't.

Like Tomasz said - that's the one goal - the other - you can "snaphot" the state of other related entity inside your table.
F.e.
#Embeddable public class Company {
String name;
String streetName;
String city;
}
#Entity public class Invoice {
#Embedded
#AttributeOverrides({
#AttributeOverride(name="name", column=#Column(name="name")),
#AttributeOverride(name="streetName", column=#Column(name="streetName")),
#AttributeOverride(name="city", column=#Column(name="city")),
})
Company seller;
#Embedded
#AttributeOverrides({
#AttributeOverride(name="name", column=#Column(name="name")),
#AttributeOverride(name="streetName", column=#Column(name="streetName")),
#AttributeOverride(name="city", column=#Column(name="city")),
})
Company customer;
}
in this example - without embedded and #AttributeOverrides any change in future of Company customer will change the data in Invoice - which is a bug - the invoice was generated for the company with old data.
It's good explained here: :)
Java - JPA #Basic and #Embedded annotations

It doesn't always have to be the ID of the class. In Domain Driven Design, you can create a component out of some of the properties of an object, e.g. in this example http://yaarunmulle.com/hibernate/hibernate-example/hibernate-mapping-component-using-annotations-1.html a student has an address component.
The Address property of Student is annotated with #Embedded to point to the Address class component.

Related

Efficient way to map a subset of entity fields as separate class in Hibernate

I'm designing a solution for dealing with complex structure (user related stuff with lots of relations) in a simplier and possibly more efficient way than getting all the related data from DB. The only part of data I really need in my use case is basically contained withing the non-relational 'main' entity fields.
As for now I extracted the basic fields from 'main' class (let it be class OldMain) to another class (let's call it abstract class Extracted), used #MappedSuperclass and created 2 classes that extends it- Basic (which is empty class as Extracted gives it all the data I need and mapped to table 'X') and Extended (which is also mapped to table 'X' but with all the extra relations). It basically works but the code structure looks odd and makes me thinking if that's a proper way of dealing with such a problem.
I also tried with lazy initiation on relational fields (which i guessed on the beginning would serve here well), but I wasn't able to get it to work as I wanted with Jackson (only non-lazy fields in JSON, without fetching lazy related data- it couldn't be serialized or fired another several dozen of relation queries).
Another thing i stumbled upon in some tutorial was making DTO from 'OldMain' entity to not touch the lazy fields but haven't tried it yet as I started with the #MappedSuperClass way.
#Table(name = "X")
#MappedSuperclass
public abstract class Extracted{
//all the non-relational fields from OldMain
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String surname;
private String userName;
private String email;
}
#Table(name = "X")
#Entity
public class Basic extends Extracted{
//empty
}
#Table(name = "X")
#Entity
public class Extended extends Extracted{
//all relational fields from OldMain, no data fields
}
Also the general question is- is there any good practices when dealing with need of using only a subset of a bigger entity?
There is no obligation for a JPA Entity to map all existing columns in the corresponding table in the database. That is, given a table my_entity with columns col1, col2, col3, the Entity mapped to this table could map only col1 and col2 and ignore col3. That being said, plus the fact that you only need the non-relational attributes, you could directly use your Extracted class with the attributes you need and ignore the fact that other relational field exists. Furthermore, if all the relational fields are nullable then you could even be able to persist new instances of Extracted class. And Jackson would only (un)marshal the declared attributes in Extracted class.
In other case, I suggest to follow the approach you already are in and define new Entity classes that extend your Extracted class with the required attributes. I don't see how "code structure looks odd", other than having a Basic class with no new attributes than Extracted - you could easily make Extracted non-abstract and use it directly, and get rid of Basic.

How does Hibernate work with normalized databases?

Preliminary Info
I'm currently trying to integrate Hibernate with my team at work. We primarily do Java web development, creating webapps that provide data to clients. Our old approach involves calling stored procedures with JDBC (on top of Oracle boxes) and storing their results in beans. However, I've heard a lot about the benefits of integrating Hibernate into a development environment like ours so I'm attempting to move away from our old habits. Note: I'm using the Hibernate JPA annotation approach due to simplicity for team adoption's sake.
Specific Problem
The specific issue I'm having currently is using Hibernate with normalized tables. We have a lot of schemas structured like so:
StateCodes (integer state_code, varchar state_name)
Businesses (integer business_id, varchar business_name, integer state_code)
I want to be able to have a single #Entity that has all of the "Businesses" fields, except instead of "state_code" it has "state_name". To my understanding, Hibernate treats #Entity classes as tables. The #OneToMany, #OneToOne, #ManyToOne annotations create relationships between entities, but this is a very simplistic, dictionary-like lookup and I feel like it doesn't apply here (or might be overkill).
One approach I've seen is
#Formula("(select state_name from StateCodes where Businesses.state_code = state_code)")
private String stateCode;
But, given Hibernate's perk of "avoiding writing raw SQL", this seems like bad practice. Not to mention, I'm extremely confused about how Hibernate will then treat this field. Does it get saved on a save operation? It's just defined as a query, not a column, after all.
So what is the best way to accomplish this?
I do not see any reason not use the standard JPA mappings in this case. Short of creating a database view and mapping an entity to that (or using the non-JPA compliant #Formula) then you will have to map as below.
Unless you are providing a means for the State to be changed then you do not need to expose the State entity to the outside world: JPA providers do not need getters/setters to be present.. Neither do you need to Map a State to Businesses:
#Entity
#Table(name = "Businesses")
public class Business{
//define id and other fields
#ManyToOne
#JoinColumn(name = "state_code")
private State state;
public String getStateName(){
return state.getName();
}
}
#Entity
#Table(name="StateCodes")
public class State{
//define id and other fields.
#Column(name = "state_name")
private String stateName;
public String getStateName(){
return stateName;
}
}

Can I create a OneToOne relationship with just the id?

In JPA is it possible to create an #OnToOne relationship with just an idea and not embedding the class? For example:
#Entity public class Relationship {
#Id
#OneToOne
private Long parentId; // instead of "private User parent;"
#Id
#OneToOne
private Long childId; // instead of "private User child;"
int type;
...
I don't mind having a getter method with a lazy fetch but I don't need one and I'd prefer not to have to pull in complete parent objects to work with child objects. Also, I want to deserialize this to JSON using just the id and not the embedded object. I can do this by adding a getter that delegates to #getParent().getId() and putting a JsonIgnore on the #getParent() method (and the same for child) but I'd prefer to get the entity to look the way I want it to from the get go without adding this stuff. Possible and if so how?
Thanks!
No. How can an Object be related to a Number? This is an O-O language after all.
Labelling something as #OneToOne is semantically equivalent to a FK in the datastore. If you just omit #OneToOne and use a number then you have a numeric column in the datastore without a FK. So JPA allows both, but one gives the benefits of a FK, whereas with the other you just pass "numbers" around with no context of what they relate to

What does #AttributeOverride mean?

I'm currently coming (back) up to speed with EJB and while I was away it changed drastically (so far for the better). However, I've come across a concept that I am struggling with and would like to understand better as it seems to be used in our (where I work, not me and all the voices in my head) code quite a bit.
Here's the example I've found in a book. It's part of an example showing how to use the #EmbeddedId annotation:
#Entity
public class Employee implements java.io.Serializable
{
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name="lastName", column=#Column(name="LAST_NAME"),
#AttributeOverride(name="ssn", column=#Column(name="SSN"))
})
private EmbeddedEmployeePK pk;
...
}
The EmbeddedEmployeePK class is a fairly straightforward #Embeddable class that defines a pair of #Columns: lastName and ssn.
Oh, and I lifted this example from O'Reilly's Enterprise JavaBeans 3.1 by Rubinger & Burke.
Thanks in advance for any help you can give me.
It's saying that the attributes that make up the embedded id may have predefined (through explicit or implicit mappings) column names. By using the #AttributeOverride you're saying "ignore what other information you have with regard to what column it is stored in, and use the one I specify here".
In the UserDetails class, I have overridden homeAddress & officeAddress with Address
This One Address POJO will act for two table in DB.
DB:
Table1 Table2
STREET_NAME HOME_STREET_NAME
CITY_NAME HOME_CITY_NAME
STATE_NAME HOME_STATE_NAME
PIN_CODE HOME_PIN_CODE
The EmbeddedEmployeePK class is a fairly straightforward #Embeddable class that defines a pair of #Columns: lastName and ssn.
Not quite - EmbeddedEmployeePK defines a pair of properties, which are then mapped to columns. The #AttributeOverride annotations allow you to override the columns to which the embedded class's properties are mapped.
The use case for this is when the embeddable class is used in different situations where its column names differ, and some mechanism is required to let you change those column mappings. For example, say you have an entity which contains two separate instances of the same embeddable - they can't both map to the same column names.
JPA tries to map field names to column names in a datasource, so what you're seeing here is the translation between the name of a field variable to the name of a column in a database.
You can override also other column properties (not just names).
Let's assume that you want to change the length of SSN based on who is embedding your component. You can define an #AttributeOverride for the column like this:
#AttributeOverrides({
#AttributeOverride(name = "ssn", column = #Column(name = "SSN", length = 11))
})
private EmbeddedEmployeePK pk;
See "2.2.2.4. Embedded objects (aka components)" in the Hibernate Annotations documentation.
In order to preserve other #Column properties (such as name and nullable) keep them on the overridden column the same as you specified on the original column.

Hibernate best approach for one Java class and multiple tables?

Put another way: How do you model/map a heavily reused child class/table to many different parent entities?
I have several entity types each being persisted into its own table:
class A --> table A
class B --> table B
....
Now I need to make each of these classes the parent of a 1:M unidirectional child collection. The collection is a history of approvals the entity has gained over time. The Child domain class is called "ApprovalItem". The Approval class is exactly the same for all types of parents.
What is the best way to map this? If I create a single table to hold all ApprovalItems, then I can't enforce a FK relation to the PK of the entity and/or I am left with a bad database design.
On the other hand, I could create an ApprovalIems table for each entity type (e.g. A_ApprovalItems, B_ApprovalItems, etc.). This seems like a good schema on the database side, but then it seems I need to create a separate domain classes in Java for each entity approval (e.g. AAprrovalItem class, BApprovalItem class, etc.). This seems like a lot of hassle and complexity to create so many new classes in Java that do nothing other than allow me to put in different JPA mapping annotations.
Is there a mapping technique in Hibernate that will allow me to have one class in Java map to several different tables depending on who the parent owner of the collection is?
I could create an ApprovalItem table for each entity type (e.g. A_ApprovalItem, B_ApprovalItem, etc.). This seems like a good schema on the database side
But
It seems i need to create a separate domain classes in Java for each entity approval (e.g. AAprrovalItem class, BApprovalItem class, etc.).
You do not need it. you can create a single ApprovalItem class and create a #OneToMany relationship between your parent classes and your ApprovalItem. Hibernate takes care to create a linked table for each relationship.
#Entity
public class ClassA {
#Id
#GeneratedValue
private Integer id;
// Hibernate will create CLASSA_APPROVALITEM to link both class
#OneToMany
private List<ApprovalItem> approvalItemList;
}
#Entity
public class ClassB {
#Id
#GeneratedValue
private Integer id;
// Hibernate will create CLASSB_APPROVALITEM to link both class
#OneToMany
private List<ApprovalItem> approvalItemList;
}
And your ApprovalItem class
#Entity
public class ApprovalItem {
#Id
#GeneratedValue
private Integer id;
// Nothing else
}
But Let's see what Java Persistence with Hibernate book talks about it
You may have shared references to the Bid objects. As suggested earlier, a User may have a collection of references to the Bid instances they made. You can’t delete an item and all its bids without removing these references first. You may get an exception if you try to commit this transaction, because a foreign key constraint may be violated.
So keep it in mind when dealing with shared references.
In order to see how the target schema looks like, you can use the following
AnnotationConfiguration configuration = new AnnotationConfiguration();
configuration
.addAnnotatedClass(ClassA.class)
.addAnnotatedClass(ClassB.class)
.addAnnotatedClass(ApprovalItem.class)
.setProperty(Environment.USER, <TYPE_YOUR_USER>)
.setProperty(Environment.PASS, <TYPE_YOUR_PASSWORD>)
.setProperty(Environment.URL, <TYPE_YOUR_URL>)
.setProperty(Environment.DIALECT, <TYPE_YOUR_DIALECT>)
.setProperty(Environment.DRIVER, <TYPE_YOUR_DRIVER>);
SchemaExport schema = new SchemaExport(configuration);
schema.setOutputFile("schema.sql");
schema.create(<DO_YOU_WANT_TO_PRINT_TO_THE_CONSOLE>, <DO_YOU_WANT_TO_EXPORT_THE_SCRIPT_TO_THE_DATABASE>);
It will generate a file called schema.sql, which contains your target schema
regards,
Chapter 8. Inheritance Mapping of Hibernate Documentation might help.
Otherwise, I see no problem having multiple ApprovalItem derived class that "do nothing", like you say, since it does differentiate the Approval, it's like having a type of approval. Seeing your model like so, I would recommend using multiple classes, even if they only inherit from your base ApprovalItem class.
Have I well understood your question or am I missing something else more subtle?

Categories