Thursday 25 December 2014

CollectionId : Adding primary key for collection table


CollectionId is used to give primary key for collection table. In previous post, emp_addresses table don’t have any primary key, if you want to add a primary key for emp_addresses table use CollectionId annotation.

@GenericGenerator(name="id_gen", strategy="hilo")
@CollectionId(
        columns = @Column(name="address_id"), 
        type=@Type(type="long"), 
        generator = "id_gen"
    )
List<Address> addresses;

@GenericGenerator is a hibernate annotation used to denote a custom generator. Above snippet uses a hilo algorithm to efficiently generate identifiers of type long.

package myFirstHibernate;

import javax.persistence.Embeddable;

@Embeddable
public class Address {
  private String street;
  private String city;
  private String state;
  private String PIN;
  private String country;
  
  public String getStreet() {
    return street;
  }
  
  public void setStreet(String street) {
    this.street = street;
  }
  
  public String getCity() {
    return city;
  }
  
  public void setCity(String city) {
    this.city = city;
  }
  
  public String getState() {
    return state;
  }
  
  public void setState(String state) {
    this.state = state;
  }
  
  public String getPIN() {
    return PIN;
  }
  
  public void setPIN(String pIN) {
    PIN = pIN;
  }
  
  public String getCountry() {
    return country;
  }
  
  public void setCountry(String country) {
    this.country = country;
  }
  
}

package myFirstHibernate;

import java.util.List;

import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumn;
import javax.persistence.Column;

import org.hibernate.annotations.CollectionId;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;

@Entity
public class Employee {
  @Id
  private int id;
  private String firstName;
  private String lastName;
  
  @ElementCollection
  @JoinTable(name="emp_addresses", joinColumns=@JoinColumn(name="emp_id"))
  @GenericGenerator(name="id_gen", strategy="hilo")
  @CollectionId(
      columns = @Column(name="address_id"), 
          type=@Type(type="long"), 
          generator = "id_gen"
      )
  List<Address> addresses;

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public List<Address> getAddresses() {
    return addresses;
  }

  public void setAddresses(List<Address> addresses) {
    this.addresses = addresses;
  }
    
}


hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

  <session-factory>
  
    <!--  Database Connection settings -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost/sample</property>
    <property name="connection.username">root</property>
    <property name="connection.password">tiger</property>
    
    <!-- Enable the logging of all the generated SQL statements to the console -->
    <property name="show_sql">true</property>
    
    <!-- Format the generated SQL statement to make it more readable, -->
    <property name="format_sql">false</property>
    
    <!-- Hibernate will put comments inside all generated SQL statements to hint what’s the generated SQL trying to do -->
    <property name="use_sql_comments">false</property>
    
    <!-- This property makes Hibernate generate the appropriate SQL for the chosen database. -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    
    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">create</property>
    
    <!-- mappings for annotated classes -->
    <mapping class="myFirstHibernate.Employee" />
    
  </session-factory>
  
</hibernate-configuration>

package myFirstHibernate;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class TestEmployee {
  
  /* Step 1: Create session factory */
  private static SessionFactory getSessionFactory() {
    Configuration configuration = new Configuration().configure();
    StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().
    applySettings(configuration.getProperties());
    SessionFactory factory = configuration.buildSessionFactory(builder.build());
        return factory;
    }
  
  public static void main(String args[]){
    Employee emp1 = new Employee();
    emp1.setId(1);
    emp1.setFirstName("Hari Krishna");
    emp1.setLastName("Gurram");
    
    Address addr1 = new Address();
    addr1.setCity("Bangalore");
    addr1.setCountry("India");
    addr1.setPIN("560037");
    addr1.setState("Karnataka");
    addr1.setStreet("Chowdeswari street");
      
    Address addr2 = new Address();
    addr2.setCity("Ongole");
    addr2.setCountry("India");
    addr2.setPIN("523169");
    addr2.setState("Andhra Pradesh");
    addr2.setStreet("Punuru");

    List<Address> addrList = new ArrayList<Address> ();
    addrList.add(addr1);
    addrList.add(addr2);
    
    emp1.setAddresses(addrList);
    
    /* To persisit data */
    SessionFactory sessionFactory = getSessionFactory();
    Session session = sessionFactory.openSession();
    session.beginTransaction();
    session.save(emp1);
    session.getTransaction().commit();
    session.close();   
  }
}


Output
Hibernate: alter table emp_addresses drop foreign key FK_o3skpa21dhfq096yt91cm0x50
Hibernate: drop table if exists Employee
Hibernate: drop table if exists emp_addresses
Hibernate: drop table if exists hibernate_unique_key
Hibernate: create table Employee (id integer not null, firstName varchar(255), lastName varchar(255), primary key (id))
Hibernate: create table emp_addresses (emp_id integer not null, PIN varchar(255), city varchar(255), country varchar(255), state varchar(255), street varchar(255), address_id bigint not null, primary key (address_id))
Hibernate: alter table emp_addresses add constraint FK_o3skpa21dhfq096yt91cm0x50 foreign key (emp_id) references Employee (id)
Hibernate: create table hibernate_unique_key ( next_hi integer )
Hibernate: insert into hibernate_unique_key values ( 0 )
Dec 21, 2014 10:28:13 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
Hibernate: insert into Employee (firstName, lastName, id) values (?, ?, ?)
Hibernate: select next_hi from hibernate_unique_key for update
Hibernate: update hibernate_unique_key set next_hi = ? where next_hi = ?
Hibernate: insert into emp_addresses (emp_id, address_id, PIN, city, country, state, street) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into emp_addresses (emp_id, address_id, PIN, city, country, state, street) values (?, ?, ?, ?, ?, ?, ?)


Table details from MySQL

mysql> select * from employee;
+----+--------------+----------+
| id | firstName    | lastName |
+----+--------------+----------+
|  1 | Hari Krishna | Gurram   |
+----+--------------+----------+
1 row in set (0.00 sec)

mysql> select * from emp_addresses;
+--------+--------+-----------+---------+----------------+--------------------+------------+
| emp_id | PIN    | city      | country | state          | street             | address_id |
+--------+--------+-----------+---------+----------------+--------------------+------------+
|      1 | 560037 | Bangalore | India   | Karnataka      | Chowdeswari street |          1 |
|      1 | 523169 | Ongole    | India   | Andhra Pradesh | Punuru             |          2 |
+--------+--------+-----------+---------+----------------+--------------------+------------+
2 rows in set (0.00 sec)

mysql> describe employee;
+-----------+--------------+------+-----+---------+-------+
| Field     | Type         | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| id        | int(11)      | NO   | PRI | NULL    |       |
| firstName | varchar(255) | YES  |     | NULL    |       |
| lastName  | varchar(255) | YES  |     | NULL    |       |
+-----------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

mysql> describe emp_addresses;
+------------+--------------+------+-----+---------+-------+
| Field      | Type         | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| emp_id     | int(11)      | NO   | MUL | NULL    |       |
| PIN        | varchar(255) | YES  |     | NULL    |       |
| city       | varchar(255) | YES  |     | NULL    |       |
| country    | varchar(255) | YES  |     | NULL    |       |
| state      | varchar(255) | YES  |     | NULL    |       |
| street     | varchar(255) | YES  |     | NULL    |       |
| address_id | bigint(20)   | NO   | PRI | NULL    |       |
+------------+--------------+------+-----+---------+-------+
7 rows in set (0.01 sec)

Prevoius                                                 Next                                                 Home

No comments:

Post a Comment