我有一个实体,我使用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?如果某些列名称改变了怎么样?
是否有其他方法可以满足我的要求?
答案 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。