To deal with persistence in Java is getting less complicated by the tools that are being offered to us. The complication lies in the fact what to choose and what kind of strategy should you choose. In my previous blog I opened the doors to JPA which i denied to exist for a couple of years. "Just another Hibernate" was my defense. Looking at it from a historical point of view, My thoughts where based on some points. Hibernate was there together with toplnk and EJB to deal with ORM before JPA. These three tools where the bases for the reference called JPA. At last I opened that small and started being interested in JPA. I have to admit it is getting to me. I really like the way the things have been setup. A lot of people that tried to explain to me that JPA gave more freedom, have been shot by me as evangelists. The fun part of the story is, that not there preaching but a project that was using JPA brought me the light.
The example:
There are a couple of ways to deal with persistence in JPA. The most easy and fun one are repositories. I have them on my list to be study. But for now there is SQL, HQL (hibernate) and JQL (jpa). Sql gives you the straight forward way to acces an database something select * from customers or update customers set name = 'john doe' where id = 1 should look familiair. In JQL this looks pretty much the same but you are not talking to the database but to the objects that are representing the database in the application called entities.
So we have a simple Java pojo for customers with a customer name (I like it simple :)):
Lets use Lombok for fun:
public class Customer {
@Id
@GeneratedValue
@Getter
@Setter
private long id;
//lombok annotations.
@Getter
@Setter
private String name;
}
//Now we make it persistable:
@Entity
//the table to point to the name is not mandotory if the class has the same name as the database table.
@Table(name="customer")
public class Customer {
@Id
@GeneratedValue
@Getter
@Setter
private long id;
//lombok annotations.
@Getter
@Setter
@Column //you could also use the name attribute if the column name in the table difffers from the class //member name.
private String name;
}
if JPA is configured correctly this class is coupled to the table now by the ORM of JPA.
But now my customers are hooked up with the products they bought from me That is going to give me an N to N relation ship. 1 customer can buy multiple products and 1 product could been bought by multiple customers. An N to N relation ship can only achieved through a coupling table in the database. It would be really annoying if the represenation of your class model should be one on one with the database. This means that you would need to model all your coupling tables which yo are not going to need to present your data.
One of the things we can do is Model it with @named queries in JPA That would look something like this:
@Entity
//the table to point to the name is not mandotory if the class has the same name as the database table.
@Table(name="customer")
//The JPA named query
@NamedQuery(name = "selectPrdFromCustomer" , query = "select c.products from Customers c where c.id = ?1 ") })
public class Customer {
private long id;
//lombok annotations.
@Getter
@Setter
@Column //you could also use the name attribute if the column name in the table difffers from the class //member name.
private String name;
//lombok annotations.
@Getter
@Setter
}
//the table to point to the name is not mandotory if the class has the same name as the database table.
@Table(name="customer")
//The JPA named query
@NamedQuery(name = "selectPrdFromCustomer" , query = "select c.products from Customers c where c.id = ?1 ") })
public class Customer {
private long id;
//lombok annotations.
@Getter
@Setter
@Column //you could also use the name attribute if the column name in the table difffers from the class //member name.
private String name;
//lombok annotations.
@Getter
@Setter
//ManyToMany is the equilevant for N to N cascading all means get all the data you can on all the levels allowed.
@ManyToMany(cascade = CascadeType.ALL)
//The CUSTOMER_PRODUCT table is the coupling table. The join collumn is the collumn where the id from this class should couple with. the inverseJoinColum is the id of the products where it should couple to.
@JoinTable(name = "CUSTOMER_PRODUCT", joinColumns = @JoinColumn(name = "product_id"), inverseJoinColumns = @JoinColumn(name = "id"))
Private List<Products> products
}
At this point you can that a normal sql query has been handled on Entity level. The interesting part is that this sql query is separated on two different places. The named query is taking responsibility for the selecting part while the ManyToMany and the JoinTable is taking the responsibility for the coupling part.
As last you can create an PersistenceController or manager and that would need to do something like this:
Public PersistenceController {
@PersistenceContext
private EntityManager em;
@Setter
@Getter
private long customerId;
public List<String getProductNames() {
public List<String> product name = em.createNamedQuery("selectPrdFromCustomer").setParameter(1, customerId).getSingleResult();
//The getSingleResult is only applicable if you really want to have one result instead of an list but then the type of the method should be also String and not al list.
}
}
Conclusion:
Ones you know how to deal with persistence like this it is easy. But to learn it can give you a bad hadache. It is worth the effort That is for sure. Just try the example that has been given and have FUN!
Geen opmerkingen:
Een reactie posten