JPA映射模型使用Composite-Keys返回null元素

Set*_* M. 5 java orm spring hibernate jpa

我使用JPA构建了我的数据模型,并使用Hibernate的EntityManager 3来访问数据.我使用HSQLDB进行测试(junit).我正在将此配置用于其他类,并且没有任何问题.

但是,最新一批表使用复合键作为主键,并且在实现时无法从数据库中检索填充的行.我没有收到错误,查询只返回null对象.

例如,如果我查询(使用jsql)"FROM Order o"返回表中所有订单的列表,我的list.size()具有适当数量的元素(2),但元素为null.

我希望有一个比我更敏锐的人能够辨别出我做错了什么.提前致谢!

(简化)表定义为:

CREATE TABLE member (
    member_id INTEGER NOT NULL IDENTITY PRIMARY KEY);

CREATE TABLE orders (
    orders_id INTEGER NOT NULL,
    member_id INTEGER NOT NULL,
    PRIMARY KEY(orders_id, member_id));

ALTER TABLE orders 
    ADD CONSTRAINT fk_orders_member 
    FOREIGN KEY (member_id) REFERENCES member(member_id);
Run Code Online (Sandbox Code Playgroud)

实体POJO由以下定义:

@Entity
public class Member extends Person implements Model<Integer>{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="MEMBER_ID", nullable=false)
    private Integer memberId;

    @OneToMany(fetch=FetchType.LAZY, mappedBy="member", cascade=CascadeType.ALL)
    private Set<Order> orderList;
}

@Entity
@Table(name="ORDERS")
@IdClass(OrderPK.class)
public class Order extends GeneralTableInformation implements Model<Integer>{

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="ORDERS_ID", nullable=false)
    private Integer orderId;

    @Id
    @Column(name="MEMBER_ID", nullable=false)
    private Integer memberId;

    @ManyToOne(optional=false, fetch=FetchType.LAZY)
    @JoinColumn(name="MEMBER_ID", nullable=false)
    private Member member;

    @OneToMany(mappedBy="order", fetch=FetchType.LAZY)
    private Set<Note> noteList;
}
Run Code Online (Sandbox Code Playgroud)

OrderPK定义了一个默认构造函数和2个属性(orderId,memberId)及其get/set方法.

public class OrderPK implements Serializable {
private static final long serialVersionUID = 1L;

private Integer orderId;
private Integer memberId;

public OrderPK() {}

public OrderPK(Integer orderId, Integer memberId) {
    this.orderId = orderId;
    this.memberId = memberId;
}

/**Getters/Setters**/

@Override
public int hashCode() {
    return orderId.hashCode() + memberId.hashCode(); 
}

@Override
public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (!(obj instanceof OrderPK))
        return false;

    OrderPK other = (OrderPK) obj;
    if (memberId == null) {
        if (other.memberId != null) return false;
    } else if (!memberId.equals(other.memberId))
        return false;
    if (orderId == null) {
        if (other.orderId != null) return false;
    } else if (!orderId.equals(other.orderId))
        return false;
    return true;
}   
Run Code Online (Sandbox Code Playgroud)

}

(抱歉长度)

entityManager在抽象类中实例化,然后由我的其他DAO扩展

protected EntityManager em;

@PersistenceContext
public void setEntityManager(EntityManager em) {
    this.em = em;
}
Run Code Online (Sandbox Code Playgroud)

并由spring上下文配置文件配置

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:dataSource-ref="dataSource" 
    p:jpaVendorAdapter-ref="jpaAdapter">
    <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    </property>
    <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
</bean>
Run Code Online (Sandbox Code Playgroud)

我的考试班

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class OrderDaoTest {

    @Autowired
    protected OrderDao dao = null;

    @Test
    public void findAllOrdersTest() {
    List<Order> ol = dao.findAll();
    assertNotNull(ol); //pass
        assertEquals(2, ol.size(); //pass
        for (Order o : ol) {
            assertNotNull(o); //fail
            ...
        } 
    }
}
Run Code Online (Sandbox Code Playgroud)

当我从Order类中删除复合键时,我能够检索数据,我不确定我对映射或配置的错误.任何帮助是极大的赞赏.

小智 6

我有同样的问题。我必须在现有数据库上创建后端,其中有一些没有主键和可为空列的表(我知道!!)。这意味着此类表的 Hibernate 实体将具有由所有表列组成的复合主键。

当我通过 JpaRepository 的 findAll 方法查询表行时,我会得到一个结果列表,其中一些结果为空值,而其他结果则正常。

我终于发现,如果组合键的某些字段为空,它会将整行呈现为空结果。

  • 在尝试了接受的答案后,这就是为我做的。因此,复合 id 中仅包含非空值是一个重要信息。 (2认同)

Set*_* M. 4

在解决这个问题一段时间后,我了解到我在错误的类中配置了我的 Id 属性。

本来我是在Order类中配置orderId和memberId

@Entity
@Table(name="ORDERS")
@IdClass(OrderPK.class)
public class Order extends GeneralTableInformation implements Model<Integer>{

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="ORDERS_ID", nullable=false)
    private Integer orderId;

    @Id
    @Column(name="MEMBER_ID", nullable=false)
    private Integer memberId;
Run Code Online (Sandbox Code Playgroud)

但是,我了解到,如果您使用 IdClass 或 EmbeddedId,则必须为 ID 类中的 Id 列进行适当的字段注释。

@Entity
@Table(name="ORDERS")

@IdClass(OrderPK.class)
public class Order extends GeneralTableInformation implements Model<Integer>{

    @Id
    private Integer orderId;

    @Id
    private Integer memberId;
}

public class OrderPK implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name="ORDERS_ID", nullable=false)
    private Integer orderId;

    @Column(name="MEMBER_ID", nullable=false)
    private Integer memberId;
}
Run Code Online (Sandbox Code Playgroud)

通过此更改,我能够通过测试返回预期结果。