使用JPA检索Box内的所有项目

时间:2014-05-11 11:13:55

标签: java jpa

每个User都有一个Box。每个Box可能包含一些Item 我的架构是:

Item

@Entity
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;

    @ManyToOne(fetch=FetchType.LAZY)
    @Column(allowsNull = "false") 
    @Unowned
    private Box location; 
    ...

Box

@Entity
public class Box {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;

    @OneToMany(mappedBy="location", cascade={CascadeType.ALL})
    private List<Item> items;
    ...

User

@Entity
public class User{
    @Id
    @Column(name="USER_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;

    @OneToOne(fetch=FetchType.LAZY, cascade={CascadeType.REMOVE})
    @Column(allowsNull = "false") 
    @JoinColumn(name="BOX_ID")
    private Box box;

如果此结构中有任何错误,请告诉我。

现在我想要检索属于Item的所有User,最好使用javax.persistence.EntityManager,但我根本不能。

我打算做的是:

Query q1 = em.createQuery("select u from User u where u.username='"+username+"'");
User user = // ... well known code

Query q2 = em.createQuery("select i from Item i where i.location='"+user.box+"'");
Item item = // ... well known code

现在我收到了这个例外:

 SELECT u FROM database.entities.Item u WHERE u.location.key='database.entities.Box@3872bb09': Can only reference properties of a sub-object if the sub-object is embedded.

1 个答案:

答案 0 :(得分:1)

首先,您不应该使用连接将动态参数传递给查询。这是低效的,如果参数包含单引号将失败,并打开您的代码到SQL注入攻击。使用命名参数:

select ... where u.username = :name
...
query.setParameter("name", username);

现在看看你的第二个查询。它搜索的项目的位置等于Box实例的toString()值。这没有意义。您必须将框作为参数传递:

Query q2 = em.createQuery("select i from Item i where i.location = :box");
q2.setParameter("box", user.getBox());

请注意,您不需要两个查询。一个就足够了:

select item from User user
inner join user.box box 
inner join box.items item 
where user.username = :name