使用主键嵌入对象的Hibernated错误

时间:2014-11-19 22:35:51

标签: java hibernate

我有一个名为Place的@MappedSuperclass,其中包含名为uniqueId和name的变量。我还有Country类和City类扩展了Place类。 City类(@Embeddable)有一个名为mayor的变量,Country类(@Entity)有一个名为president的变量。 Country类有两个嵌入对象,名为capital_city和largest_city。当我持久化Country对象时,我得到Hibernate错误,指出country_id(使用@AttributeOverride从uniqueId重命名)没有默认值。 insert语句实际上没有country_id的值。当我查看create语句时,它已将largest_city_id定义为主键...我不明白为什么Hibernate会以这种方式运行。我需要将country_id作为主键,并简单地嵌入两个City对象。代码如下。

// Place class
@MappedSuperclass
public abstract class Place  {  

    private String uniqueId;
    private String name;

    @Id
    public String getUniqueId() {
        return uniqueId;
    }

    public void setUniqueId(String uniqueId) {
        this.uniqueId = uniqueId;
    }

    @Column(nullable=true, unique=false)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

// Country class
@Entity
@AttributeOverride (name="uniqueId", column=@Column(name="country_id"))
public class Country extends Place {
    private City capitalCity;
    private City largestCity;
    private String president = "";

    public Country() { }
    public Country(String id, String name, City capital, City largest, String prez) {
        this.setUniqueId(id);
        this.setName(name);
        capitalCity = capital;
        largestCity = largest;
        president = prez;
    }

    public String getPresident() {
        return president;
    }

    public void setPresident(String president) {
        this.president = president;
    }

    @Embedded
    @AttributeOverrides ({
        @AttributeOverride (name="uniqueId", column=@Column(name="capital_city_id")),
        @AttributeOverride (name="name", column=@Column(name="capital_city_name")),
        @AttributeOverride (name="mayor", column=@Column(name="capital_city_mayor"))
    })
    public City getCapitalCity() {
        return capitalCity;
    }

    public void setCapitalCity(City capitalCity) {
        this.capitalCity = capitalCity;
    }

    @Embedded
    @AttributeOverrides ({
        @AttributeOverride (name="uniqueId", column=@Column(name="largest_city_id")),
        @AttributeOverride (name="name", column=@Column(name="largest_city_name")),
        @AttributeOverride (name="mayor", column=@Column(name="largest_city_mayor"))
    })
    public City getLargestCity() {
        return largestCity;
    }

    public void setLargestCity(City largestCity) {
        this.largestCity = largestCity;
    }
}

// City class
@Embeddable
public class City extends Place {

    private String mayor;

    public City() {}
    public City(String m, String id, String name) {
        mayor = m;
        this.setUniqueId(id);
        this.setName(name);
    }

    public String getMayor() {
        return mayor;
    }

    public void setMayor(String mayor) {
        this.mayor = mayor;
    }
}

// Main
import test.City;
import test.Country;

public class Main {
    public static void main(String[] args) {
        City capital = new City("Tom Smith","1010","Fairview");
        City largest = new City("Jo Somebody","2010","Crestfall");

        Country country = new Country("USA","United States", 
                                       capital, largest, "George Jefferson");

        AnnotationConfiguration cfg = new AnnotationConfiguration();
        Session session = cfg.configure("hibernate.cfg.xml").buildSessionFactory().openSession();
        Transaction t=session.beginTransaction();
        session.persist(country);
        t.commit();
        session.close();
    }
}

// Bibernate Create SQL codes
Hibernate: drop table if exists Country
Hibernate: create table Country (country_id varchar(255) not null, name varchar(255), 
           capital_city_id varchar(255) not null, capital_city_mayor varchar(255), 
           capital_city_name varchar(255), largest_city_id varchar(255) not null, 
           largest_city_mayor varchar(255), largest_city_name varchar(255), 
           president varchar(255), primary key (largest_city_id))
Hibernate: insert into Country (name, capital_city_mayor, capital_city_name, 
           largest_city_mayor, largest_city_name, president, largest_city_id) values 
           (?, ?, ?, ?, ?, ?, ?)

请注意,主键是最大的city_id,而不是country_id。

// Hibernate error message
Caused by: java.sql.SQLException: Field 'country_id' doesn't have a default value

请帮助!!!我将Hibernate表示法添加到现有代码库中,因此我没有太多自由来修改代码。希望这可以通过正确的Hibernate注释来实现。

1 个答案:

答案 0 :(得分:0)

我认为@MappedSuperclass只能通过@Entity s扩展,而不是@Embeddable s。 The documentation

  

指定一个类,其映射信息应用于从其继承的实体

无论如何,我认为问题是当@Embed City Country中你还嵌入了第二个@Id属性时。您有来自@Id的{​​{1}}继承的Country属性以及来自嵌入式Place的{​​{1}}属性。对于@Id,您基本上有2 City。也许不是让uniqueIds成为Country,而是让它成为没有任何JPA注释的界面:

Place

您可以获得多态性的好处,无需弄清楚正确的JPA映射或必须[ab]使用@MappedAttribute