20

I should start out by saying that I am fairly new to Java EE and that I do not have a strong theoretical background in Java yet.

I'm having trouble grasping how to use JPA together with interfaces in Java. To illustrate what I find hard I created a very simple example.

If I have two simple interfaces Person and Pet:

public interface Person
{
    public Pet getPet();
    public void setPet(Pet pet);
}

public interface Pet
{
    public String getName();
}

And an Entity PersonEntity which implements Person as well as a PetEntity which implements Pet:

@Entity
public class PersonEntity implements Person
{
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private PetEntity pet;

    @Override
    public void setPet(Pet pet)
    {
        /* How do i solve this? */
    }
}

@Entity
public class PetEntity implements Pet
{
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String name;

    /* Getters and Setters omitted */

}

How do I properly handle the case in the setPet method in which I want to persist the relationships between the two entities above?

The main reason I want to use interfaces is because I want to keep dependencies between modules/layers to the public interfaces. How else do I avoid getting a dependency from e.g. my ManagedBean directly to an Entity?

If someone recommends against using interfaces on entities, then please explain what alternatives methods or patterns there are.

Hash
  • 4,647
  • 5
  • 21
  • 39
Niklas Norin
  • 355
  • 1
  • 3
  • 9

1 Answers1

18

You can use targetEntity property in the relationship annotation.

@Entity
public class PersonEntity implements Person {
    private Long id;

    private Pet pet;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

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

    @Override
    @OneToOne(targetEntity = PetEntity.class)
    public Pet getPet() {
        return pet;
    }        

    public void setPet(Pet pet) {
        this.pet = pet;
    }
}
Mairbek Khadikov
  • 7,939
  • 3
  • 35
  • 51
  • 1
    Are you sure it will work? You're using implicit field access, but set the `@OneToOne` annotation on the setter. Moreover, even with the property access, will this annotation work? Shouldn't it be on getter rather than setter? – Piotr Nowicki Jan 22 '12 at 22:37
  • 1
    Mairbek, and what about mixing field na property access? Do you think that this part of JPA 2.0 spec is relevant in this case: *"The behavior of applications that mix the placement of annotations on fields and properties within an entity hierarchy without explicitly specifying the Access annotation is undefined."*? – Piotr Nowicki Jan 22 '12 at 22:51
  • 1
    Works as long as there is only 1 implementation of Person of course. When you have more than 1 then you would need explicit support in the implementation for interface fields – user383680 Jan 25 '12 at 08:12