2

我正在使用SqlResultSetMapping注释Entity(SqlResultSetMapping 需要一个带有 Id 的实体)来告诉 Hibernate 如何Foo使用本机查询结果数据填充实例。

非持久化实体:

@SqlResultSetMapping(name = "fooMapping", entities = @EntityResult(entityClass = Foo.class))
@Entity
public class Foo {
    @Id
    public Long row_id;
    public String name;
}

本机查询:

String sql = "SELECT id AS row_id, friendlyName AS name FROM SomeTable"; 
Query q = JPA.em().createNativeQuery(sql, "fooMapping");
List<Foo> fooList = q.getResultList();

问题是,为我自动创建了一个名为“Foo”的表(在开发模式下使用 Play!Framework),但 Foo 不是模型,不应该被持久化。

我如何指示hibernate不要创建这个表?

4

2 回答 2

2

一旦它可用于您的持久层,使用@ConstructorResult将非常有用。在那之前,有一种特定于 Hibernate 的方法使用 anorg.hibernate.SQLQuery和 an org.hibernate.transform.ResultTransformer,它不依赖于@SqlResultSetMapping. 因为一个 POJO 被填充,Hibernate 发现没有@Entity自动变成一个表。

非持久 POJO:

public class Foo {
    public Long row_id;
    public String name;
}

结果转换器:

public static class FooResultTransformer implements ResultTransformer {

    @Override
    public List transformList(List list) { return list; }

    @Override
    public Object transformTuple(Object[] tuple, String[] aliases) {
        List<String> aliasList = Arrays.asList(aliases);
        Foo foo = new Foo();
        foo.row_id = ((Number) getValue(tuple, aliasList, "row_id", 0L))
            .longValue();
        foo.name = (String) getValue(tuple, aliasList, "name", null);
        return foo;
    }

    private static Object getValue(Object[] tuple, List<String> aliases,
            String field, Object defaultValue)
    {
        // unchecked for berevity
        if (tuple[aliases.indexOf(field)] == null) {
            return defaultValue;
        }
        return tuple[aliases.indexOf(field)];
    }

}

本机 SQL 查询:

String sql = "SELECT id AS row_id, friendlyName AS name FROM SomeTable";
Session session = JPA.em().unwrap(Session.class);
SQLQuery q = session.createSQLQuery(sql);

q.setResultTransformer( new FooResultTransformer() );
List<Foo> fooList = q.list();
于 2013-10-29T20:46:18.380 回答
1

不幸的是,这并不容易...

如果您使用 JPA 2.1 对 @ConstructorResult 的支持(似乎只有 hibernate 4.3.0.Beta2 支持,所以您可能没有使用),您可以使用 @ConstructorResult 如下:

@SqlResultSetMapping(name="fooMapping", 
  classes={ 
    @ConstructorResult(targetClass=Foo.class, columns={
        @ColumnResult(name="row_id", type=Integer.class),
        @ColumnResult(name="name", type=String.class)
    })
  }
)

public class Foo {

    public Long row_id;
    public String name;

    public Foo(Long rowId, String name) {
    ...
    }

}
于 2013-10-14T20:12:16.223 回答