【问题标题】:@MapKeyJoinColumn showing as null in mapping table@MapKeyJoinColumn 在映射表中显示为空
【发布时间】:2020-12-10 02:19:59
【问题描述】:

我是休眠新手,目前正在尝试使用实体类型为键和值进行映射。我在映射表中保留密钥(country_id)时遇到问题,因为它在列名下一直表示为nullmapkey_country_id,即使我明确使用@MapKeyJoinColumn 将列名指定为@987654325 @。

有关问题的更多上下文:

这是一个基本问题,我有一个带有Map<Country, Capital> 属性的Continent 实体。所以我写了以下代码:

大陆实体

@Entity
public class Continent {
        
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long cont_id;
    
    private String continent;

    @OneToMany(mappedBy="cname")
    @MapKeyJoinColumn(name ="country_id",nullable=false)
    private Map<Country, Capital> countries;

    //   followed by setters and getters...
}

资本实体

@Entity
public class Capital {

    private String capital;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long capital_id;

    @ManyToOne
    @JoinTable(name="cont_cap",
        joinColumns= @JoinColumn(name="capital_id"),
        inverseJoinColumns =@JoinColumn(name="cont_id")
    )
    private Continent cname;

    @OneToOne
    @JoinColumn(name="country_id")
    private Country country;
    
    // followed by setters and getters...
}

国家实体

@Entity
public class Country {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long country_id;

    private String country;

    //  followed by setters and getters...
}

主要方法

public static void main(String[] args) {
    SessionFactory sesfac = new AnnotationConfiguration().configure().buildSessionFactory();
    
    Session session= sesfac.openSession();
    
    Transaction tx = session.beginTransaction();
    //country2
    Country country2= new Country();
    country2.setCountry("USA");
    
    Capital cap2= new Capital();
    cap2.setCapital("Washington, D.C.");
    cap2.setCountry(country2);
    
    Continent cont2= new Continent();
    cont2.setCname("North America");
    HashMap<Country, Capital> hm2 = new HashMap<Country, Capital>();
    hm2.put(country2, cap2);
    cont2.setCountries(hm2);
    cap2.setCname(cont2);
            
    session.save(country2);
    session.save(cap2);
    session.save(cont2);
    tx.commit();
    session.close();
}

【问题讨论】:

    标签: hibernate hibernate-mapping


    【解决方案1】:

    我猜你应该在这种情况下使用@MapKey 注释而不是@MapKeyJoinColumn

    @Entity
    public class Continent {
        
        @OneToMany(mappedBy="cname", cascade = {CascadeType.PERSIST})
        @MapKey(name ="country")
        private Map<Country, Capital> countries;
    
        // ...
    }
    

    正如documentation 中解释的那样:

    @MapKey 注释用于定义实体属性,用作相关java.util.Map 的键。

    请注意,我将cascade = {CascadeType.PERSIST} 添加到@OneToMany。您还可以通过以下方式更正您的 Capital 实体:

    @Entity
    public class Capital {
    
        @OneToOne(cascade = {CascadeType.PERSIST})
        @JoinColumn(name="country_id")
        private Country country;
        
        // followed by setters and getters...
    }
    

    然后持久化操作将如下所示:

    Country country = new Country();
    country.setCountry("USA");
        
    Capital capital = new Capital();
    capital.setCapital("Washington, D.C.");
    capital.setCountry(country);
        
    Continent continent = new Continent();
    continent.setCname("North America");
     
    HashMap<Country, Capital> countries = new HashMap<Country, Capital>();
    countries.put(country, capital);
    continent.setCountries(countries);
    capital.setCname(continent);
    
    // It will save also Country and Capital due to the CascadeType.PERSIST usage
    session.persist(continent);
    

    【讨论】:

    • 嗨 SternK,感谢您的回复,我尝试使用 @MapKey 并且它有效,但它完全删除了 mapkey_country_id。有没有办法将映射键列保留在连接表中?
    • 不清楚你到底想用mapkey_country_id做什么。如果您像 Continent - Capital 一样使用双向关系,则只能在此关系的一侧(通常在 @ManyToOne 一侧)指定连接列
    • 我认为将所有三个关系都包含在连接表中可能会更清楚,因为这会创建一个集中的表以便于参考。包含所有者实体以及 mapkey 列和 mapvalue 列的连接表是否不常见?实际上,我希望创建一个包含continent_id、country_id 和capital_id 的连接表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-16
    • 2013-12-18
    • 1970-01-01
    • 2020-04-23
    • 2018-10-05
    • 2018-12-04
    相关资源
    最近更新 更多