【问题标题】:JPA Entity Creation - Objects vs. "Primitives"JPA 实体创建 - 对象与“原语”
【发布时间】:2011-08-09 16:44:37
【问题描述】:

我有一个关于实体创建的问题。假设我有以下表格

create table "foo" (
  "id"          integer primary key,
  "name"        varchar
);

create table "bar" (
  "id"          integer primary key,
  "name"        varchar,
  "fk_foo"      integer references foo(id)
);

我想知道哪个最适合实体,在实体类中使用 foo 对象作为外键引用,还是在实体中使用整数。

使用 Netbeans 6.9 我生成了以下实体:

@Entity
@Table(name = "bar")
@NamedQueries({
    @NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b"),
    @NamedQuery(name = "Bar.findById", query = "SELECT b FROM Bar b WHERE b.id = :id"),
    @NamedQuery(name = "Bar.findByName", query = "SELECT b FROM Bar b WHERE b.name = :name")})
public class Bar implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "name")
    private String name;
    @JoinColumn(name = "fk_foo", referencedColumnName = "id")
    @ManyToOne
    private Foo foo;

    public Bar() {
    }


@Entity
@Table(name = "foo")
@NamedQueries({
    @NamedQuery(name = "Foo.findAll", query = "SELECT f FROM Foo f"),
    @NamedQuery(name = "Foo.findById", query = "SELECT f FROM Foo f WHERE f.id = :id"),
    @NamedQuery(name = "Foo.findByName", query = "SELECT f FROM Foo f WHERE f.name = :name")})
public class Foo implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "name")
    private String name;
    @OneToMany(mappedBy = "foo")
    private Collection<Bar> barCollection;

    public Foo() {
    }

现在,当我必须创建一个新的 Bar 对象时,我还必须创建一个新的 Foo 对象。所以我创建了以下栏。请记住,我将 setter 和除默认构造函数之外的所有构造函数都排除在实体之外。

酒吧 bar1 = 新酒吧 (1); bar1.setName("小麦"); bar1.setFoo(new Foo(1));

与对 Foo 使用整数字段类型相反:

酒吧 bar2 = 新酒吧 (1); bar2.setName("GlaDOS"); bar2.setFoo(1);

我自己更喜欢第二种方法。有没有理由选择第一条路线更好?我遇到的一个问题是在解组 XML 时,我已经组合了实体和 JAXB 对象,在这种情况下,Foo 对象被设置为完全为空的 Foo 对象,而不是 id 为 1 的 Foo 对象。

你怎么看?

【问题讨论】:

  • 请注意,我知道 Integer 对象不是原始对象,我只是想不出更好的方式来描述它,对象 vs 对象听起来不适合。

标签: java netbeans entity jpa-2.0 netbeans-6.9


【解决方案1】:

您似乎在询问是否使用 Integer Object 或 int 数据类型。如果是这样,我会推荐 int 数据类型。当 Java 意识到将数值放入 Integer 和 Double 对象既麻烦又浪费内存空间时,Java 提出了他们。对象是指存储您放入其中的所有值的位置,从而允许您放入多个变量。数据类型只是存储数据。

【讨论】:

  • 感谢您的回答,但我真的想问的是使用 Foo 对象而不是表示该 Foo 对象的 id 值的整数对象更好
【解决方案2】:

嗯,它被称为对象关系映射:)。如果您没有发现 JPA 的附加功能比更简单的 JDBC 包装器更有价值,那么还有更多轻量级的替代方案可以将数据库列值填充到对象中。

映射对象为您做的第一件事就是允许您在 JPQL 中自然地编写连接。您不能在 JPQL 中进行任意连接,它们必须定义为对象映射。

例如,如果您在 bar 上只有 id 的数字值,并且您想找到一个具有特定 foo 的最终结果

select b from Bar b, Foo f where bar.fooId = f.id and f.name = :fooName;

而如果您将其映射为您可以编写的普通对象引用方式

select b from Bar b where b.foo.name = :fooName;

根据您使用的数据库以及它是否/如何重写查询,第一个查询中的笛卡尔积可能是坏消息。

其次,如果你不映射你的对象,你就不能使用传递持久性。您又回到了使用 EntityManager 显式地导致每个单独的插入和更新,就好像它只是一个 JDBC 包装器一样。通过传递持久性(CASCADE 设置)将所有显式持久化/合并插入/更新抽象到 ORM 层是 JPA 提供的主要功能之一,而不是更简单的 JDBC 包装器。

例如,如果您在@OneToMany 中用CascadeType.PERSIST 标记您的酒吧列表,那么您可以通过这样做来制作新的酒吧:

beginTransaction();
Foo foo = em.find(Foo.class, 1);
Bar newBar = new Bar();
//set up your Bar
foo.getBarCollection().add(newBar);
commitTransaction();

完成!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-04
    • 2012-05-10
    • 2018-04-13
    • 2013-08-30
    • 2014-11-12
    • 2012-02-27
    • 2017-04-04
    相关资源
    最近更新 更多