我对数据相关的技术很陌生,而且我在很多问题上苦苦挣扎。我的代码与Spring Data Neo4j有关,但我认为这个问题也可能与其他框架有关(比如JPA实现)。
为简单起见,假设我有两个相关实体
@NodeEntity public class A { @RelatedTo Set<B> bs /* Other fields, getters and setters*/ }
@NodeEntity public class B { @RelatedTo A a; /* Other fields, getters and setters*/}
两个@Repository来访问它们
@Repositoty
public interface ARepository extends CRUDRepository<A> { /* The usual methods based on name */ }
@Repositoty
public interface BRepository extends CRUDRepository<B> { /* The usual methods based on name */ }
和服务层上的两个接口
@Service
public interface AService { /* Some useful methods such as CRUD operations*/ }
@Service
public interface BService { /* Some useful methods such as CRUD operations*/ }
显然,这两个接口都有一个实现所用特定数据库方法的类(在本例中为AServiceNeo4j
和BServiceNeo4j
)
好的,在所有这些样板代码之后,这是真正的问题:
bs
?在声明字段(private Set<B> bs = new HashSet<B>();
)时,我已经看到许多人直接在POJO类中执行此操作。这是一个好的解决方案吗?它不会对性能产生负面影响吗?更一般地说,这个解决方案的优点和缺点是什么,而不是,例如,在@Service
类(如下面的代码)上执行此操作?addB()
方法是否有意义(再次,如下面的示例)?我还没有看到这个解决方案;相反,在某些例子中,我看到这个方法直接在POJO类中声明(所以addB(B b)
方法)。在其他示例中,我根本没有看到addB()
方法;相反,业务逻辑只调用a.getBs().add(new B())
。什么是最佳解决方案?为什么?我建议的解决方案是那样的
@Service
public class AServiceNeo4j
{
/* The other usual methods based on name */
public void addB(A a, B b)
{
// Start transaction, start try block
if (a.getBs() == null)
a.setBs(new HashSet<B>() );
a.getBs().add(b);
// Store a, add catch and finally blocks
}
}
因此,根据我的业务逻辑,我可以这样做:
A a = new A();
AService aService = // get the service bean from the applicationContext
aService.create(a);
B b = new B();
aService.addB(a, b);
而不是
A a = new A();
AService aService = // get the service bean from the applicationContext
aService.create(a);
B b = new B();
a.getB(s).add(b); // To work, the set should be instantiated in the POJO class (see point 1)
aService.update(a);
两种解决方案的优点是什么?建议的方式是什么?
此外,对于这两种解决方案,对象都不会被框架自动更新。我的意思是,对于第一个解决方案,调用a.getBs().size()
返回0(或null,取决于POJO类的实现)。对于调用b.getA()
,
要使这些方法正常工作,我必须从数据存储中检索本地对象以获得更新的值。像
这样的东西a = aService.find(a); // or aService.fetch(a);
a.getBs().size();
或
b = bService.find(b); // or bService.fetch(b);
b.getA();
这是为什么?它不应该由底层框架自动完成吗?如果没有,这是继续进行的标准方式吗?
答案 0 :(得分:1)
关于初始化集合的位置,我已经采用了@NodeEntity
声明字段(private Set<B> bs = new HashSet<B>();
时的良好做法。有一些弹簧数据示例 - neo4j以这种方式完成。请参阅example。
要向Collection
添加元素,您可以考虑在同一个POJO中添加方法来执行此操作。示例(请记住,集已经初始化)
@NodeEntity
public class A {
@RelatedTo
Set<B> bs = new HashSet<>();
public void addB(B b) {
bs.add(b);
}
}
因此,在您的服务层中,您可以直接找到实体A
,然后添加B
。
然后,如果您希望框架能够自动获取集合,则除了@Fetch
之外,还需要添加注释@Related
。例如:
@Fetch
@RelatedTo
Set<B> bs = new HashSet<>();
对于那些以spring-data-neo4j开头的人来说是个好问题。我也一直在努力解决这些问题。我会等待更多的答案,希望其他人可以分享他们的经验。
希望它有所帮助。