Writing CRUDRepository's findBy() method on a

2020-08-25 05:41发布

问题:

I'm kind of new to Spring JPA, so I apologize in advance if my question sounds basic. I have 2 entity objects: OrderInfo, and PersonInfo. The classes are as below:

@Entity
@Table(name="order_info")
@NamedQuery(name="OrderInfo.findAll", query="SELECT o FROM OrderInfo o")
public class OrderInfo implements Serializable {

    @Column(name="order_number")
    private String orderNumber;

    //bi-directional many-to-one association to PersonInfo
    @ManyToOne
    @JoinColumn(name="person_id")
    private PersonInfo personInfo;

    public String getOrderNumber() {
        return this.orderNumber;
    }

    public void setOrderNumber(String orderNumber) {
        this.orderNumber = orderNumber;
    }

    public PersonInfo getPersonInfo() {
        return this.personInfo;
    }

    public void setPersonInfo(PersonInfo personInfo) {
        this.personInfo = personInfo;
    }


}

And the Person entity:

@Entity
@Table(name="person_info")
@NamedQuery(name="PersonInfo.findAll", query="SELECT p FROM PersonInfo p")
public class PersonInfo implements Serializable {

    //bi-directional many-to-one association to OrderInfo
    @OneToMany(mappedBy="personInfo")
    private List<OrderInfo> orderInfos;

    public List<OrderInfo> getOrderInfos() {
        return this.orderInfos;
    }

    public void setOrderInfos(List<OrderInfo> orderInfos) {
        this.orderInfos = orderInfos;
    }

    public OrderInfo addOrderInfo(OrderInfo orderInfo) {
        getOrderInfos().add(orderInfo);
        orderInfo.setPersonInfo(this);

        return orderInfo;
    }

    public OrderInfo removeOrderInfo(OrderInfo orderInfo) {
        getOrderInfos().remove(orderInfo);
        orderInfo.setPersonInfo(null);

        return orderInfo;
    }

}

These two classes were auto-generated in Eclipse using JPA's create entityfromtable option.

Now, I'm trying to write a CRUDRepository to get OrderInfo given an orderNumber, and personId. If I had a personId field in the OrderInfo object, I could have written something like

@Repository
public interface OrderRepository extends CrudRepository<OrderInfo, Integer>{
    public OrderInfo findByPersonIdAndOrderNumber(@Param("personId") Long personId, @Param("orderNumber") String orderNumber);

}

However, now the OrderInfo entity does not have a personId. Instead, it has a reference to a Person (Again, I did not write the entity classes. They were auto-generated by Eclipse). How should I write the findBy() method now?

Thanks in advance.

回答1:

I've found another solution, let's assume we have a User entities and Message entities.

@Entity
public class Message {

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

    @NotNull
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime date;

    @ManyToOne
    @JoinColumn(name = "id_user_sender")
    private User userSender;

    @NotNull
    private Long idUserReceiver;

    @NotNull
    @Length(min = 10)
    private String message;

    @NotNull
    private String idConversation;

    @NotNull
    Boolean userHasRead;

    //Getters and Setters

}



@Entity
public class User implements Serializable {

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

    //Some other properies like email,name etc
    //Getters and setters
}

Now i need to find all messages by id_user_sender.

public interface MessageRepository extends JpaRepository<Message,Long>,TransactionRepositoryCustom {
    List<Message> findByUserSenderId(Long idUser);
}

Explantion: In the Message entity i have a User Object named 'userSender'. The userSender has a field named 'id'.

So 'findByUserSenderId' search for the id in the userSender Object.

Another possibilty is to pass a full User object to the message repository as in the example below: (The User object must contain only the id)

public interface MessageRepository extends JpaRepository<Message,Long>,TransactionRepositoryCustom {
   List<Message> findByUserSender(User user);
}


回答2:

Use a JPQL query:

@Query("select o from OrderInfo o where o.orderNumber = :orderNumber"
       + " and o.personInfo.id = :personId")


回答3:

I believe this is what you are looking for: Spring Data JPA - Repositories - Property expressions

For your code, this might work (I didn't try it out):

public OrderInfo findByPersonInfoIdAndOrderNumber(Long personInfoId, String orderNumber);



回答4:

I think you need to update the spring data jpa version. I am currently using spring-data-jpa-2.0.2.RELEASE and it works well.

Also, it works for both the cases. You can define your interface method as -

List<Message> findByUserSender(User user);

or -

List<Message> findByUserSenderId(Long idUser);

Both these methods will create a left outer join on user_sender table to fetch the desired Message(s);