如果实体已存在,如何按属性返回实体?

时间:2015-08-17 13:20:08

标签: java hibernate

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

    @Column(length = 2)
    private String code; //EN, DE, US

    public Language(String code) {
        this.code = code;
    }
}

@Entity
public class ProductText {
    @OneToOne(Cascade.ALL)
    private Language lang;
}

ProductText text = new ProductText();
text.setLang(new Language("en")); //what if "en" exists?
dao.save(text);

现在,当我持久保存ProductText时,每次都会生成一个新的Language对象。

我是否可以阻止这种情况,如果存在code = 'en'的语言表条目,则应该链接此现有实体。

我最初的目标是不必在产品文本表中多次重复countryCodeString“EN”,而只是引用id。但这真的有意义吗?我是否应该在没有额外表格的情况下使用普通String? (我后来想查询productTexts where lang = 'de')列表。

之前执行像dao.findByLang("en")这样的选择的唯一更改是? 或者是否还有一些hibernate功能可以支持这个而不需要自己显式执行查询?

3 个答案:

答案 0 :(得分:1)

你处理价值" en"进一步还是直接显示?如果仅用于显示目的,我只会存储字符串,但如果您想通过使用外键ID减少冗余,则 创建包含语言字符串{{1}的Entity这可以通过实体管理器持久存储,并且在持久重用之前必须从实体管理器中获取。

答案 1 :(得分:1)

如果该语言只有三种不同的可能值,您也可以使用这样的枚举:

public enum Language {

    EN("EN"),
    DE("DE"),
    US("US");

    private String code; //EN, DE, US

    public Language(String code) {
        this.code = code;
    }
    // Getter...
}

@Entity
public class ProductText {
    @Enumerated(EnumType.STRING)
    // Or @Enumerated(EnumType.ORDINAL)
    private Language lang;
}

EnumType.STRING将枚举作为String存储在数据库中,而EnumType.ORDINAL将它存储为int。 Int可能更高效,但如果在枚举中插入新值,映射可能会更改。字符串更灵活,因为它将使用枚举成员的名称。

在这两种情况下,您不必管理单独的实体,并且hibernate不会创建额外的表,并且它比使用普通字符串更安全类型。

答案 2 :(得分:0)

如果Language中唯一的值是2或3个字母的字符串,为什么不将字符串作为成员呢?这将更快更有效。