Nowbody calls me Ignacio. I’m plunchete, man!

Relations with JPA

Posted in Google Summer of Code, Java, JPA, OpenJPA by plunchete on May 15, 2007

Continuing with the JPA Basic Example I’ve written another example with relations between Entities.

In the example we have three entities: Organization, Project, Student with this relations:

  • A organization has many projects
  • Each projects is asigned to one organization
  • A project has one student
  • Each student is asigned to one project

For this relations we need three anotations: @OneToOne, @OneToMany and @ManyToOne.

Now we are going to write our Organization entity:

@Entity
public class Organization {	

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "organization_id")
	private int idOrganization;

	@Basic
	@Column(nullable = false, length = 100)
	private String name;

	@OneToMany(cascade = CascadeType.ALL,
			mappedBy = "organization")
	@InverseLogical("organization")
	private ArrayList<Project> projects;

	public Organization(String name) {
		this.name = name;
	}
        // Getters and Setters
}

We used the anotation @OneToMany because we’re going to persist and Organization and we want to add projects to the organization and when we persist the organization the projects will be persist too.
The property cascade = CascadeType.ALL indicates that when we persist, remove, refresh or merge this entity all the entities held in this field would be persist, remove, delete or update. This property can have other values as:

  • CascadeType.PERSIST – When we persist and entity all the entities held in this field persist too. If you want to persist an entity and the fields dont use it fails.
  • CascadeType.REMOVE – When we delete an entity all the entities held in this field delete too.
  • CascadeType.REFRESH – When we refresh an entity all the entities held in this field refresh too.
  • CascadeType.MERGE – When we merde an entity all the entities held in this flied merged too

The following anotations are equivalent:

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE,
             CascadeType.REFRESH, CascadeType.MERGE})
private ArrayList<Project> projects;

And

@OneToMany(cascade = CascadeType.ALL)
private ArrayList<Project> projects;

The propery mappedBy = “organization” indicates who’s the name of the organization entity in the project object.

The annotation @InverseLogical(“organization”) indicates that a field should be maintained bidirectionally. When we use this annotation OpenJPA managed the relation and updates the field oganization in the project entity.

Now we are going to write our Project entity:

@Entity
public class Project {	

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "project_id")
	private int idProject;

	@Basic
	@Column(nullable = false)
	private String name;

	@ManyToOne
	@JoinColumn(name="organization_id", nullable = false)
	private Organization organization;

	@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
	@JoinColumn(name="student_id")
	@InverseLogical("project")
	private Student student;

	public Project(String name) {
		this.name = name;
	}
        // Getters and Setters
}

Now we use the annotation @ManyToOne to indicate the relation.
The annotation @JoinColumn(name=”organization_id”, nullable = false) indicates that the field can’t be null and the name on the table.
And finally we use the annotation @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) to manage our one-to-one relation between the project entity and the student.

Now we are going to write our Student entity:

@Entity
public class Student {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int studentId;

	@Basic
	@Column(nullable = false)
	private String name;

	@OneToOne
	@JoinColumn(name="project_id")
	private Project project;

	public Student(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
        // Getters and Setters
}

And our persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    version="1.0">
    <persistence-unit name="example" transaction-type="RESOURCE_LOCAL">
        <class>example.Organization</class>
		<class>example.Project</class>
		<class>example.Student</class>
        <properties>
            <property name="openjpa.jdbc.SynchronizeMappings"
                value="buildSchema"/>
            <property name="openjpa.ConnectionURL"
                value="jdbc:mysql://localhost/OpenJPARelations"/>
            <property name="openjpa.ConnectionDriverName"
                value="com.mysql.jdbc.Driver"/>
            <property name="openjpa.ConnectionUserName"
                value="user"/>
            <property name="openjpa.ConnectionPassword"
                value="password"/>
	    <property name="openjpa.InverseManager"
		value="true"/>
	    <property name="openjpa.Log"
		value="File=../RelationsExample.log,
                DefaultLevel=WARN,SQL=TRACE"/>
        </properties>
    </persistence-unit>
</persistence>

The property openjpa.InverseManager is necesary to manage inverse relations.
Finally the writer and the reader:

public void insertValues() {
	EntityManagerFactory factory = Persistence.
		createEntityManagerFactory("example", System.getProperties());

	EntityManager em = factory.createEntityManager();
	em.getTransaction().begin();
	Organization organization =
		new Organization(" The Apache Software Foundation");

	Project project =
		new Project("Streaming LOB support (for OpenJPA)");
	Student student = new Student("Ignacio Andreu");
	project.setStudent(student);
	organization.addProject(project);

	project = new Project("Maven Dependency Visualization");
	student = new Student("Peter Kolbus");
	project.setStudent(student);
	organization.addProject(project);

	em.persist(organization);

	organization = new Organization(" Mono Project");
	project = new Project("Gendarme Tasks");
	student = new Student("Néstor Salceda");
	project.setStudent(student);
	organization.addProject(project);

	em.persist(organization);

	em.getTransaction().commit();
	em.close();
	factory.close();
}

public void readValues() {
	EntityManagerFactory factory = Persistence.
	createEntityManagerFactory("example", System.getProperties());

	EntityManager em = factory.createEntityManager();

	Query q = em.createQuery("select o from Organization o");

	for (Organization organization : (List)q.getResultList()) {
		System.out.println("Organization: "
			+ organization.getName());
		if (organization.getProjects() != null &&
			organization.getProjects().size() > 0) {
			for (Project p : organization.getProjects()) {
				System.out.println("-"
					+ p.getName()
                                        + " asigned to "
					+ p.getStudent().getName());
			}
		} else {
			System.out.println("No proyects yet");
		}
	}
	em.close();
	factory.close();
}

The output is:

[java] Organization: The Apache Software Foundation
[java] -Streaming LOB support (for OpenJPA) asigned to Ignacio Andreu
[java] -Maven Dependency Visualization asigned to Peter Kolbus
[java] Organization: Mono Project
[java] -Gendarme Tasks asigned to Néstor Salceda

And this is all for the moment!

8 Responses

Subscribe to comments with RSS.

  1. […] and how to delete objects in JPA Continuing with the example Relations with JPA now I’ve written another example about querys and deleting […]

  2. techiexchange said, on December 14, 2007 at 5:03 pm

    Hi,
    Its a very nice and simple tutorial.

    Thanks
    http://techieexchange.wordpress.com/

  3. Vishwa said, on August 12, 2008 at 7:49 am

    It gives very good understanding for beginers.

  4. plunchete said, on August 12, 2008 at 9:38 am

    Thanks Vishwa🙂

  5. Brzhk said, on November 16, 2008 at 7:59 pm

    @Inverselogical = i couldnt find it in the JPA reference, where does it come from?

  6. plunchete said, on November 17, 2008 at 12:14 am

    Hi Brzhk,

    @InverseLogical is part of Apache OpenJPA and not part of the standard.

  7. Puneet Swarup said, on December 25, 2008 at 10:29 am

    Nice one.

    What is the default cacadeType if none is defined. Also what if i dont want to change/update the related entity, which cascadeType should be used.

  8. Gnana said, on October 6, 2009 at 6:19 pm

    * It is a nice tutorial for JPA relation concept


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: