休眠时的ColumnTransformer

时间:2015-02-26 09:36:39

标签: java hibernate jpa orm jpql

我有一个实体,我使用ColumnTransformer进行绑定和提取值:

@Entity
class BPoint {
    @Id
    private Integer id;

    @ColumnTransformer(read = "astext(shape)", write = "toshape(?)")
    private Shape shape;

}

道:

class BPointDao {
    @Autowired
    private EntityManager em;

    @Override
    public Page<BPoint> findAll(Pageable pageable) {
        Query q = em.createQuery("from BPoint");
        List<BPoint> r = q.getResultList();
        int total = em.createQuery("select count(*)  from BPoint").getFirstResult();
        return new PageImpl(r, pageable, total);
    }
    @Override
    public Integer save(BPoint hbds) {
        em.persist(hbds);
        return hbds.getId();
    }
}

它工作正常,但是一旦我需要进行一些需要使用sql函数的查询,我遇到了一些问题,例如这个有效的本机sql:

select * from BPoint h where inside(h.shape, 100) = 1;

首先我尝试使用这样的hql:

Query q = em.createNativeQuery("select astext(shape) from BPoint h where inside(h.shape, ?) = 1");

但是我发现生成的sql包含

之类的东西

...... where inside(astext(h.shape),100).....

似乎{s}函数ColumnTransformer read中使用的inside值不是预期的。

所以我尝试使用这样的本机sql查询:

Query q = em.createNativeQuery("select * from BPoint h where inside(h.shape, ? = 1");

不能执行sql,但无法正确映射结果。

然后我必须像这样添加select fileds

Query q = em.createNativeQuery("select id,astext(shape) from BPoint h where inside(h.shape, ? = 1");

但是,如果我的实体有很多文件说它超过20?如果某些列名称改变了怎么样?

是否有其他方法可以满足我的要求?

2 个答案:

答案 0 :(得分:4)

首先尝试将返回类型提供给您的本机查询:

Query q = em.createNativeQuery("select * from BPoint h where inside(h.shape, ? = 1", BPoint.clss);
List<BPoint> result = q.getResultList();

或者您可以尝试这样做:

Session session = em.unwrap(Session.class);
List<BPoint> points = (List<BPoint>) session.createSQLQuery("SELECT {h.*} FROM BPoint {h} WHERE inside({h}.shape, ? = 1")
    .addEntity("h", BPoint.class)
.list();

Hibernate特定的API允许您将本机查询结果映射到实体。

答案 1 :(得分:1)

你可以创建一个自定义拦截器&#34;修复&#34; SQL将内部替换所有&#34; inside(astext(#REF))(#REF)

您必须覆盖org.hibernate.Interceptor#onPrepareStatement(String sql)。 input参数包含您可以按照描述修改的sql。