Java 在SpringHibernate项目中,初始化实体集合(POJO)的正确方法是什么?

Java 在SpringHibernate项目中,初始化实体集合(POJO)的正确方法是什么?,java,hibernate,spring,architecture,collections,Java,Hibernate,Spring,Architecture,Collections,我有一个POJO类,比如Foo,它有一组其他实体实例,比如bar。 此外,对于这样的项目还有标准的杂项类:Foo和Bar的service和dao 我希望BarService获得与某些Foo关联的Bar实例集。现在我有了下面的代码,我认为它在概念上是不好的 public class Foo { Set<Bar> bars; public Set<Bar> getBars() { if (bars == null) retur

我有一个POJO类,比如Foo,它有一组其他实体实例,比如bar。 此外,对于这样的项目还有标准的杂项类:Foo和Bar的service和dao

我希望BarService获得与某些Foo关联的Bar实例集。现在我有了下面的代码,我认为它在概念上是不好的

 
public class Foo {
    Set<Bar> bars;

    public Set<Bar> getBars() {
        if (bars == null)
            return ( bars = new HashSet() );
        return bars;
    }
}

公开课Foo{
设置横杆;
公共设置getbar(){
如果(条==null)
返回(bar=newhashset());
返回杆;
}
}

公共类BarServiceImpl{
公共列表getListOfBars(Foo-Foo){
返回新的ArrayList(foo.getBars());
}
}
3个问题: 在哪里初始化Foo的集合更好? 哪些特定的集合和列表更适合此类目的? 我当前的实现存在哪些概念性问题,以及如何做得更好


提前感谢。

我倾向于在服务层初始化集合,在那里我也保留事务处理。因此,我可以在我的BaseDAO中使用一个方法,通过将集合名称传递到要立即获取(初始化)的方法中,使我可以使用反射初始化项目中任何实体的任何集合:

一个更详细的例子:

您的实体可以是一组带有getter和setter的简单字段。您需要注意的是如何关联对象和填充对象的方法。
ORMAPI提供了使用对象而不是SQL的自由。您应该小心选择何时初始化对象的字段。例如,如果您有一个对象person,其中包括姓名、年龄、联系人集合和访问过的城市。在您感兴趣的人的姓名和年龄而不是联系人和城市的情况下,您应该只加载姓名和年龄。这意味着联系人和城市应该延迟加载。
如果对联系人感兴趣,则只加载联系人,而不加载整个person对象或通过person对象。您可能希望仅使用Dao/服务和显式定义方法加载联系人集,以加载对象的特定方面(使用反向关联)。
有关hibernate的一些最佳实践,请访问。 更新: 1) 实体不会自行填充。一种流行的方法是使用DAO来完成这项工作。你的实体可能很简单

public class Foo {
    private Set<Bar> bar=new HashSet<Bar>();
    public Set<Bar> getBar {
        return bar;
    }
    public void setBar(Bar bar) {
        this.bar = bar;
    }
}
公共类Foo{
private Set bar=new HashSet();
公共设置栏{
返回杆;
}
公共空间立根杆(杆){
这个.bar=bar;
}
}
2) 您可以在另一层(也称为服务层)中管理事务

在哪里初始化Foo的集合更好

大多数时候,我在声明集合时初始化集合,这是Hibernate建议的。引用文件:

Hibernate需要持久的 不能声明集合值字段 作为接口类型。例如:

public class Product {
    private String serialNumber;
    private Set parts = new HashSet();

    public Set getParts() { return parts; }
    void setParts(Set parts) { this.parts = parts; }
    public String getSerialNumber() { return serialNumber; }
    void setSerialNumber(String sn) { serialNumber = sn; }
}
实际接口可能是
java.util.Set
java.util.Collection
java.util.List
java.util.Map
java.util.SortedSet
java.util.SortedMap
或任何您需要的 喜欢(“任何你喜欢的”意思就是你 必须编写一个实现 属于
org.hibernate.usertype.UserCollectionType

注意实例变量是如何定义的 已使用的实例初始化
HashSet
。这是最好的方法 初始化集合值 新实例化的 (非持久性)实例。当你 通过以下方式使实例持久化 例如,调用
persist()
, Hibernate实际上将取代
HashSet
的实例 Hibernate自己的
设置

如果将其保留为空是您业务的一部分,我的建议是使用(通用)链接管理方法初始化它:

public class Foo {
    ...
    private Set<Bar> bars;
    ...
    public void addBar(Bar bar) {
        if (this.bars == null) {
            this.bars = new HashSet<Bar>();
        }
        this.bars.add(bar);
    }
}
公共类Foo{
...
私人酒吧;
...
公共无效添加栏(栏){
如果(this.bar==null){
this.bar=新的HashSet();
}
此.bar.add(bar);
}
}
哪些特定的集合和列表更适合此类目的

这完全取决于您需要的语义。
集合
不允许重复,而
列表
允许重复并引入位置索引

我当前的实现存在哪些概念性问题,以及如何做得更好

  • 我不会在getter中执行任务。
    • 如果此时集合假定为
      null
      ,则将其设为
      null
  • 我看不出你的服务有什么附加价值
    • 为什么不直接调用
      foo.getbar()
    • 为什么要转换集合

  • 有用的代码片段,我肯定会在我未来的项目中使用这种方法。但现在我正在做一个非常小的自学项目,春季冬眠之王hello world,所以就目前而言,这对我来说非常复杂。不管怎样,谢谢你,谢谢。所以,如果我理解正确的话,我必须在DAO中定义方法,它将以用户ID作为参数,并执行hibernate查询来加载所需的方面?对吧?没错。当您进一步了解它时,请阅读有关如何加载特定字段集、延迟加载、反向关联、条件和HQL的内容。我发现HQL非常有效地控制对象中加载的内容。根据具体情况,您可以选择加载哪些字段,从而避免不必要的SQL联接或n+1问题。实现jsf视图层需要转换集合,但如果我想将datatable与set一起使用,我必须实现自定义datamodel。至于“为什么不调用foo.getBars()?”这不坏吗,我的视图层将与实体直接通信,而不是与它的服务通信?至于在申报时的初始化:不是吗
    public class Foo {
        private Set<Bar> bar=new HashSet<Bar>();
        public Set<Bar> getBar {
            return bar;
        }
        public void setBar(Bar bar) {
            this.bar = bar;
        }
    }
    
    public class Product {
        private String serialNumber;
        private Set parts = new HashSet();
    
        public Set getParts() { return parts; }
        void setParts(Set parts) { this.parts = parts; }
        public String getSerialNumber() { return serialNumber; }
        void setSerialNumber(String sn) { serialNumber = sn; }
    }
    
    public class Foo {
        ...
        private Set<Bar> bars;
        ...
        public void addBar(Bar bar) {
            if (this.bars == null) {
                this.bars = new HashSet<Bar>();
            }
            this.bars.add(bar);
        }
    }