質問

I have created a data-access layer containing Spring Data Neo4j classes which are accessed behind interfaces.

For example, I have a Car interface and a CarNode class that uses SDN annotations like @RelatedTo :

@RelatedTo(elementClass = CarNode.class, type = "drives", direction = OUTGOING)
private Set<Driver> drivers;

If you look closely, you'll see that the @RelatedTo refers to the CarNode class and the drivers is defined as Set<Driver> (and not Set<DriverNode>).

This works fine.

Now I would like to use @Fetch to enable eager-loading.

If I simply do :

@RelatedTo(elementClass = CarNode.class, type = "drives", direction = OUTGOING)
@Fetch
private Set<Driver> drivers;

I get the following error :

Type interface org.my.project.Driver is neither a @NodeEntity nor a @RelationshipEntity

Is this possible to tell @Fetch that it should expect DriverNode, just like it is possible with @RelatedTo when we use elementClass attribute?

I would like to avoid breaking my current architecture. Thanks for your hints!

役に立ちましたか?

解決 2

It's been more than a year since I posted this question. Reading it again, the problem is obvious to me now : I was completely misunderstanding and misusing the elementClass attribute. When I wrote:

@RelatedTo(elementClass = CarNode.class, type = "drives", direction = OUTGOING)
private Set<Driver> drivers;

this is wrong, wrong, wrong.

The solution to my original question is to use the interface inside the field declaration (private Set<Driver> drivers;), and the concrete implementation of the interface in the "elementClass" attribute of @RelatedTo.

This is how it works now in my project:

@RelatedTo(elementClass = DriverNode.class, type = "drives", direction = OUTGOING)
private Set<Driver> drivers = new HashSet<Driver>(0);

So, the only place where you have to use the DriverNode concrete class is inside elementClass attribute. You don't need to use generics at all.

Foot-note : I don't use @Fetch anymore.

他のヒント

I've faced a similar issue and I solved it using the implementation class in the Set field, i.e.

@RelatedTo(type = "drives", direction = OUTGOING)
@Fetch private Set<DriverNode> drivers;

After all the drivers collection is private, hence it's an implementation detail. To enforce access by interface you can declare get/set methods which return/take as parameter instances of the interface type:

public Set<? extends Driver> get Drivers() {
    return drivers;
}

public void setDrivers(Set<? extends Driver> drivers) {
    this.drivers = (Set<DriverNode>) drivers;
}

In the set method you have to cast the Set<Driver> collection to Set<DriverNode>, but this doesn't break the interface rule, since it's again an implementation detail hidden by the public interface.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top