在hibernate中,如何编写查询以使用复合键检索数据?

时间:2011-12-02 07:20:30

标签: java hibernate

这里我有一个名为receipt的表,其主键是一个复合键,与其他类Receipt_compoundKey一起引用,其中包含两个名为voucher_idcompany_id的变量,

如何使用company_id=1;

等条件从收据中检索数据

收据:

@Entity

@Table(name = AMAM_Constants.tb_name.RECEIPT_FROM, catalog = AMAM_Constants.db_name)
public class Receipt implements Serializable {

@Id
private Receipt_CompoundKey id;
@OneToOne
@JoinColumn(name = "FROM_LEDGER")
private Ledger fromLedger;
@Column(name = "VOU_DATE")
private Date voucher_Date;
@Column(name = "TOTAL_AMOUNT")
private double total_amount;
@Column(name = "ACTIVE")
private char active;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = AMAM_Constants.tb_name.RECEIPT_FROM_LINK_TO, joinColumns = {
    @JoinColumn(name = "COMPANY_ID"),
    @JoinColumn(name = "VOUCHER_ID")
}, inverseJoinColumns = {
    @JoinColumn(name = "RECP_TO")})
private List<Receipt_To> recptToList = new ArrayList<Receipt_To>();
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = AMAM_Constants.tb_name.RECEIPT_FROM_LINK_ADJMTS, joinColumns = {
    @JoinColumn(name = "COMPANY_ID"),
    @JoinColumn(name = "VOUCHER_ID")
}, inverseJoinColumns = {
    @JoinColumn(name = "RECPT_ADJS")})
private List<Receipt_Adj> recptAdjments = new ArrayList<Receipt_Adj>();

public List<Receipt_Adj> getRecptAdjments() {
    return recptAdjments;
}

public void setRecptAdjments(List<Receipt_Adj> recptAdjments) {
    this.recptAdjments = recptAdjments;
}

public List<Receipt_To> getRecptToList() {
    return recptToList;
}

public void setRecptToList(List<Receipt_To> recptToList) {
    this.recptToList = recptToList;
}

public char getActive() {
    return active;
}

public void setActive(char active) {
    this.active = active;
}

public double getTotal_amount() {
    return total_amount;
}

public void setTotal_amount(double total_amount) {
    this.total_amount = total_amount;
}

public Ledger getFromLedger() {
    return fromLedger;
}

public void setFromLedger(Ledger fromLedger) {
    this.fromLedger = fromLedger;
}

public Receipt_CompoundKey getId() {
    return id;
}

public void setId(Receipt_CompoundKey id) {
    this.id = id;
}

public Date getVoucher_Date() {
    return voucher_Date;
}

public void setVoucher_Date(Date voucher_Date) {
    this.voucher_Date = voucher_Date;
}

}

Receipt_CompoundKey:

@Embeddable
public class Receipt_CompoundKey implements Serializable {

@Column(name = "VOUCHER_ID")
private long voucher_Id;
@Column(name = "COMPANY_ID")
private long company_Id;

public Receipt_CompoundKey() {
}

public Receipt_CompoundKey(long voucher_Id) {
    this.voucher_Id = voucher_Id;
}

public Receipt_CompoundKey(long voucher_Id, long company_Id) {
    this.company_Id = company_Id;
    this.voucher_Id = voucher_Id;
}

public long getCompany_Id() {
    return company_Id;
}

public void setCompany_Id(long company_Id) {
    this.company_Id = company_Id;
}

public long getVoucher_Id() {
    return voucher_Id;
}

public void setVoucher_Id(long voucher_Id) {
    this.voucher_Id = voucher_Id;
}

}

查询:

String query = "from Receipt where active='Y' and  id=:id ";
begin();
objList = getSession().createQuery(query).setLong("id", key.getCompany_Id()).setLong("id", key.getVoucher_Id()).list();
commit();

2 个答案:

答案 0 :(得分:1)

您可以像使用单列ID一样执行此操作:

getSession().createQuery(query).setParameter("id", key);

您也可以查询密钥的各个值,但这里不需要:

String query = "select r from Receipt r where r.active = 'Y'"
               + " and id.company_Id = :companyId"
               + " and id.voucher_Id = :voucherId";
objList = getSession().createQuery(query)
                      .setLong("companyId", key.getCompany_Id()) 
                      .setLong("voucherId", key.getVoucher_Id())
                      .list();

请注意,尊重Java命名约定:voucherId而不是voucher_Id,ReceiptCompoundKey而不是Receipt_CompoundKey等。

答案 1 :(得分:1)

首先你必须做一个select而不仅仅是"from Receipt where active='Y' and id=:id "(我认为这是一个不可思议的错误,但万一它不是):

String query = "
SELECT receipt 
FROM Receipt receipt 
WHERE receipt.id = :yourId "

为了创建查询,我使用EntityManager。这是一个示例类以及它如何为我工作。

public class EntityManagerUtil {

    private static EntityManagerFactory entityManagerFactory = null;

    private static final ThreadLocal<EntityManager> entitymanager = 
        new ThreadLocal<EntityManager>();

    private static final ThreadLocal<Map<Class<?>, Set<Serializable>>>collectionFieldNameValues = 
        new ThreadLocal<Map<Class<?>, Set<Serializable>>>();

    public static EntityManagerFactory initializeEntityManagerFactory( String persistenceUnit ) {
        if ( entityManagerFactory == null ) {

            entityManagerFactory = Persistence.createEntityManagerFactory( persistenceUnit );
        }
        return entityManagerFactory;
    }

    public static EntityManager getEntityManager() {

        EntityManager entityManager = entitymanager.get();
        // Create a new EntityManager
        if ( entityManager == null || !entityManager.isOpen()) {
            entityManager = entityManagerFactory.createEntityManager();
            entitymanager.set( entityManager );
        }
        return entityManager;
    }

    public static void close() {
        final EntityManager entityManager = entitymanager.get();
        entitymanager.set( null );
        if ( entityManager != null && entityManager.isOpen()) { 
            entityManager.close();
        }
        if ( entityManagerFactory != null && entityManagerFactory.isOpen()) {
            entityManagerFactory.close();
        }
    } 
}

在您的类中,您希望获取数据,首先使用持久性单元初始化EntityManagerFactory(以免它称为ReceiptPersistence)。这是它的样子:

EntityManagerUtil.initializeEntityManagerFactory("ReceiptPersistence");
EntityManagerUtil.getEntityManager().getTransaction().begin();
Query getReceiptWithId = EntityManagerUtil.getEntityManager().createQuery(query);
getReceiptWithId.setParameter("yourId", idThatYouWant);

现在,当您的查询准备就绪时,您可以使用getSingleResult()从中获取单个结果:

Receipt receipt = (Receipt) getReceiptWithId.getSingleResult();
EntityManagerUtil.getEntityManager().getTransaction().commit();
EntityManagerUtil.getEntityManager().close();

如果您这样做是try / catch(推荐),您可以执行EntityManagerUtil.getEntityManager().getTransaction().rollback();当您对数据库进行一些更改时需要它。

我使用ThreadLocal确保每个用户都有1个线程。