JPA:如何将本机查询结果集转换为POJO类集合

时间:2012-10-22 13:34:05

标签: java jpa

我在我的项目中使用JPA。

我来到一个查询,我需要在五个表上进行连接操作。所以我创建了一个返回五个字段的本机查询。

现在我想将结果对象转换为包含相同五个字符串的java POJO类。

JPA中是否有任何方法可以直接将该结果转换为POJO对象列表?

我来到以下解决方案..

@NamedNativeQueries({  
    @NamedNativeQuery(  
        name = "nativeSQL",  
        query = "SELECT * FROM Actors",  
        resultClass = db.Actor.class),  
    @NamedNativeQuery(  
        name = "nativeSQL2",  
        query = "SELECT COUNT(*) FROM Actors",  
        resultClass = XXXXX) // <--------------- problem  
})  

现在在resultClass中,我们是否需要提供一个实际的JPA实体类? 要么 我们可以将它转换为包含相同列名的任何JAVA POJO类吗?

23 个答案:

答案 0 :(得分:177)

我找到了几个解决方案。

使用映射实体(JPA 2.0)

使用JPA 2.0无法将本机查询映射到POJO,只能通过实体完成。

例如:

Query query = em.createNativeQuery("SELECT name,age FROM jedi_table", Jedi.class);
@SuppressWarnings("unchecked")
List<Jedi> items = (List<Jedi>) query.getResultList();

但在这种情况下,Jedi必须是映射的实体类。

此处避免未经检查的警告的替代方法是使用命名的本机查询。因此,如果我们在实体中声明本机查询

@NamedNativeQuery(
 name="jedisQry", 
 query = "SELECT name,age FROM jedis_table", 
 resultClass = Jedi.class)

然后,我们可以简单地做:

TypedQuery<Jedi> query = em.createNamedQuery("jedisQry", Jedi.class);
List<Jedi> items = query.getResultList();

这更安全,但我们仍然限制使用映射实体。

手动制图

我尝试了一些解决方案(在JPA 2.1到来之前)使用一些反射来对POJO构造函数进行映射。

public static <T> T map(Class<T> type, Object[] tuple){
   List<Class<?>> tupleTypes = new ArrayList<>();
   for(Object field : tuple){
      tupleTypes.add(field.getClass());
   }
   try {
      Constructor<T> ctor = type.getConstructor(tupleTypes.toArray(new Class<?>[tuple.length]));
      return ctor.newInstance(tuple);
   } catch (Exception e) {
      throw new RuntimeException(e);
   }
}

此方法基本上采用元组数组(由本机查询返回),并通过查找具有相同字段数和相同类型的构造函数将其映射到提供的POJO类。

然后我们可以使用方便的方法,如:

public static <T> List<T> map(Class<T> type, List<Object[]> records){
   List<T> result = new LinkedList<>();
   for(Object[] record : records){
      result.add(map(type, record));
   }
   return result;
}

public static <T> List<T> getResultList(Query query, Class<T> type){
  @SuppressWarnings("unchecked")
  List<Object[]> records = query.getResultList();
  return map(type, records);
}

我们可以简单地使用以下技术:

Query query = em.createNativeQuery("SELECT name,age FROM jedis_table");
List<Jedi> jedis = getResultList(query, Jedi.class);

JPA 2.1 with @SqlResultSetMapping

随着JPA 2.1的到来,我们可以使用@SqlResultSetMapping注释来解决问题。

我们需要在实体的某处声明一个结果集映射:

@SqlResultSetMapping(name="JediResult", classes = {
    @ConstructorResult(targetClass = Jedi.class, 
    columns = {@ColumnResult(name="name"), @ColumnResult(name="age")})
})

然后我们就这么做:

Query query = em.createNativeQuery("SELECT name,age FROM jedis_table", "JediResult");
@SuppressWarnings("unchecked")
List<Jedi> samples = query.getResultList();

当然,在这种情况下,Jedi不需要是映射的实体。它可以是常规的POJO。

使用XML映射

我是那些发现在我的实体中添加所有这些@SqlResultSetMapping非常具有侵略性的人之一,我特别不喜欢实体中命名查询的定义,所以或者我在META-INF/orm.xml文件中做了所有这些:

<named-native-query name="GetAllJedi" result-set-mapping="JediMapping">
    <query>SELECT name,age FROM jedi_table</query>
</named-native-query>

<sql-result-set-mapping name="JediMapping">
        <constructor-result target-class="org.answer.model.Jedi">
            <column name="name" class="java.lang.String"/>
            <column name="age" class="java.lang.Integer"/>
        </constructor-result>
    </sql-result-set-mapping>

这些都是我所知道的解决方案。如果我们可以使用JPA 2.1,最后两个是理想的方式。

答案 1 :(得分:87)

JPA提供了一个SqlResultSetMapping,它允许您将本机查询的任何返回映射到实体或自定义类

编辑 JPA 1.0不允许映射到非实体类。仅在JPA 2.1中添加ConstructorResult以将返回值映射为java类。

另外,对于OP的计数问题,应该足以使用单个ColumnResult

定义结果集映射

答案 2 :(得分:10)

是的,使用JPA 2.1很容易。你有非常有用的注释。它们简化了你的生活。

首先声明您的本机查询,然后是结果集映射(定义数据库返回到POJO的数据的映射)。写下你的POJO课程(为简洁起见,不包括在内)。最后但并非最不重要的:在DAO中创建一个方法(例如)来调用查询。这对我来说是一个dropwizard(1.0.0)应用程序。

首先在实体类中声明本机查询:

@NamedNativeQuery (
name = "domain.io.MyClass.myQuery",
query = "Select a.colA, a.colB from Table a",
resultSetMapping = "mappinMyNativeQuery")   // must be the same name as in the SqlResultSetMapping declaration

您可以在下面添加结果集映射声明:

@SqlResultSetMapping(
name = "mapppinNativeQuery",  // same as resultSetMapping above in NativeQuery
   classes = {
      @ConstructorResult( 
          targetClass = domain.io.MyMapping.class
          columns = {
               @ColumnResult( name = "colA", type = Long.class),  
               @ColumnResult( name = "colB", type = String.class)
          }
      )
   } 
)

稍后在DAO中,您可以将查询称为

public List<domain.io.MyMapping> findAll() {
        return (namedQuery("domain.io.MyClass.myQuery").list());
    }

就是这样。

答案 3 :(得分:7)

如果您使用Spring-jpa,这是答案和此问题的补充。如果有任何缺陷,请更正此问题。我主要使用三种方法来实现&#34;将结果Object[]映射到pojo&#34;根据我遇到的实际需要:

  1. JPA内置方法就足够了。
  2. JPA内置方法是不够的,但定制的sql及其Entity就足够了。
  3. 前2人失败,我必须使用nativeQuery。 以下是示例。 pojo期待:

    public class Antistealingdto {
    
        private String secretKey;
    
        private Integer successRate;
    
        // GETTERs AND SETTERs
    
        public Antistealingdto(String secretKey, Integer successRate) {
            this.secretKey = secretKey;
            this.successRate = successRate;
        }
    }
    
  4. 方法1 :将pojo更改为界面:

    public interface Antistealingdto {
        String getSecretKey();
        Integer getSuccessRate();
    }
    

    和存储库:

    interface AntiStealingRepository extends CrudRepository<Antistealing, Long> {
        Antistealingdto findById(Long id);
    }
    

    方法2 : 存储库:

    @Query("select new AntistealingDTO(secretKey, successRate) from Antistealing where ....")
    Antistealing whatevernamehere(conditions);
    

    注意:POJO构造函数的参数序列在POJO定义和sql中必须相同。

    方法3 : 在@SqlResultSetMapping中使用@NamedNativeQueryEntity作为Edwin Dalorzo答案中的示例。

    前两种方法会调用许多中间处理程序,例如自定义转换器。例如,AntiStealing定义secretKey,在保留之前,插入转换器来加密它。这将导致前两个方法返回转换后的secretKey,这不是我想要的。虽然方法3将克服转换器,但返回secretKey将与存储的相同(加密的)。

答案 4 :(得分:4)

首先声明注释:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultEntity {
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultColumn {
    int index();
}

然后按如下方式注释您的POJO:

@NativeQueryResultEntity
public class ClassX {
    @NativeQueryResultColumn(index=0)
    private String a;

    @NativeQueryResultColumn(index=1)
    private String b;
}

然后编写注释处理器:

public class NativeQueryResultsMapper {

    private static Logger log = LoggerFactory.getLogger(NativeQueryResultsMapper.class);

    public static <T> List<T> map(List<Object[]> objectArrayList, Class<T> genericType) {
        List<T> ret = new ArrayList<T>();
        List<Field> mappingFields = getNativeQueryResultColumnAnnotatedFields(genericType);
        try {
            for (Object[] objectArr : objectArrayList) {
                T t = genericType.newInstance();
                for (int i = 0; i < objectArr.length; i++) {
                    BeanUtils.setProperty(t, mappingFields.get(i).getName(), objectArr[i]);
                }
                ret.add(t);
            }
        } catch (InstantiationException ie) {
            log.debug("Cannot instantiate: ", ie);
            ret.clear();
        } catch (IllegalAccessException iae) {
            log.debug("Illegal access: ", iae);
            ret.clear();
        } catch (InvocationTargetException ite) {
            log.debug("Cannot invoke method: ", ite);
            ret.clear();
        }
        return ret;
    }

    // Get ordered list of fields
    private static <T> List<Field> getNativeQueryResultColumnAnnotatedFields(Class<T> genericType) {
        Field[] fields = genericType.getDeclaredFields();
        List<Field> orderedFields = Arrays.asList(new Field[fields.length]);
        for (int i = 0; i < fields.length; i++) {
            if (fields[i].isAnnotationPresent(NativeQueryResultColumn.class)) {
                NativeQueryResultColumn nqrc = fields[i].getAnnotation(NativeQueryResultColumn.class);
                orderedFields.set(nqrc.index(), fields[i]);
            }
        }
        return orderedFields;
    }
}

使用以上框架如下:

String sql = "select a,b from x order by a";
Query q = entityManager.createNativeQuery(sql);

List<ClassX> results = NativeQueryResultsMapper.map(q.getResultList(), ClassX.class);

答案 5 :(得分:3)

可以执行展开过程以将结果分配给非实体(即Beans / POJO)。程序如下。

List<JobDTO> dtoList = entityManager.createNativeQuery(sql)
        .setParameter("userId", userId)
        .unwrap(org.hibernate.Query.class).setResultTransformer(Transformers.aliasToBean(JobDTO.class)).list();

用于JPA-Hibernate实现。

答案 6 :(得分:1)

不确定是否适合这里,但是我有类似的问题,并找到以下简单的解决方案/示例供我使用:

private EntityManager entityManager;
...
    final String sql = " SELECT * FROM STORE "; // select from the table STORE
    final Query sqlQuery = entityManager.createNativeQuery(sql, Store.class);

    @SuppressWarnings("unchecked")
    List<Store> results = (List<Store>) sqlQuery.getResultList();

就我而言,我不得不在其他地方使用在Strings中定义的SQL部分,所以我不能只使用NamedNativeQuery。

答案 7 :(得分:1)

在休眠模式下,您可以使用此代码轻松映射本机查询。

private List < Map < String, Object >> getNativeQueryResultInMap() {
String mapQueryStr = "SELECT * FROM AB_SERVICE three ";
Query query = em.createNativeQuery(mapQueryStr);
NativeQueryImpl nativeQuery = (NativeQueryImpl) query;
nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List < Map < String, Object >> result = query.getResultList();
for (Map map: result) {
    System.out.println("after request  ::: " + map);
}
return result;}

答案 8 :(得分:1)

使用结果集的旧样式

@Transactional(readOnly=true)
public void accessUser() {
    EntityManager em = this.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    session.doWork(new Work() {
        @Override
        public void execute(Connection con) throws SQLException {
            try (PreparedStatement stmt = con.prepareStatement(
                    "SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")) {
                ResultSet rs = stmt.executeQuery();
                ResultSetMetaData rsmd = rs.getMetaData();
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    System.out.print(rsmd.getColumnName(i) + " (" + rsmd.getColumnTypeName(i) + ") / ");
                }
                System.out.println("");
                while (rs.next()) {
                    System.out.println("Found username " + rs.getString("USERNAME") + " name " + rs.getString("NAME") + " email " + rs.getString("EMAIL") + " passe " + rs.getString("PASSE") + " email " + rs.getInt("LOGIN_TYPE"));
                }
            }
        }
    });
}

答案 9 :(得分:1)

使用休眠模式:

@Transactional(readOnly=true)
public void accessUser() {
EntityManager em = repo.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    org.hibernate.SQLQuery q = (org.hibernate.SQLQuery) session.createSQLQuery("SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u").addScalar("username", StringType.INSTANCE).addScalar("name", StringType.INSTANCE).addScalar("email", StringType.INSTANCE).addScalar("passe", StringType.INSTANCE).addScalar("loginType", IntegerType.INSTANCE)
        .setResultTransformer(Transformers.aliasToBean(User2DTO.class));

    List<User2DTO> userList = q.list();
}

答案 10 :(得分:0)

由于其他人已经提到了所有可能的解决方案,我正在分享我的解决方案。

在我Postgres 9.4的情况下,在使用Jackson时,

//Convert it to named native query.
List<String> list = em.createNativeQuery("select cast(array_to_json(array_agg(row_to_json(a))) as text) from myschema.actors a")
                   .getResultList();

List<ActorProxy> map = new ObjectMapper().readValue(list.get(0), new TypeReference<List<ActorProxy>>() {});

我相信您可以在其他数据库中找到相同内容。

另外,仅供参考,JPA 2.0 native query results as map

答案 11 :(得分:0)

您需要的是带有构造函数的DTO:

public class User2DTO implements Serializable {

    /** pode ser email ou id do Google comecando com G ou F para Facebook */
    private String username;

    private String password;

    private String email;

    private String name;

    private Integer loginType;

    public User2DTO(Object...fields) {
        super();
        this.username = (String) fields[0];
        this.name = (String) fields[1];
        this.email = (String) fields[2];
        this.password = (String) fields[3];
        this.loginType = (Integer) fields[4];
    }

并命名为:

EntityManager em = repo.getEntityManager();
        Query q = em.createNativeQuery("SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u");
        List<Object[]> objList = q.getResultList();
        List<User2DTO> ooBj = objList.stream().map(User2DTO::new).collect(Collectors.toList());

答案 12 :(得分:0)

使用休眠模式:

@Transactional(readOnly=true)
public void accessUser() {
    EntityManager em = repo.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    org.hibernate.SQLQuery q = (org.hibernate.SQLQuery) session.createSQLQuery("SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")
        .addScalar("username", StringType.INSTANCE).addScalar("name", StringType.INSTANCE)
        .addScalar("email", StringType.INSTANCE).addScalar("passe", StringType.INSTANCE)
        .addScalar("loginType", IntegerType.INSTANCE)
        .setResultTransformer(Transformers.aliasToBean(User2DTO.class));

    List<User2DTO> userList = q.list();
}

答案 13 :(得分:0)

如果您使用的是Spring,则可以使用org.springframework.jdbc.core.RowMapper

以下是一个例子:

public List query(String objectType, String namedQuery)
{
  String rowMapper = objectType + "RowMapper";
  // then by reflection you can instantiate and use. The RowMapper classes need to follow the naming specific convention to follow such implementation.
} 

答案 14 :(得分:0)

使用ResultSet的旧样式

@Transactional(readOnly=true)
public void accessUser() {
    EntityManager em = this.getEntityManager();
    org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
    session.doWork(new Work() {
        @Override
        public void execute(Connection con) throws SQLException {
            try (PreparedStatement stmt = con.prepareStatement(
                    "SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")) {
                ResultSet rs = stmt.executeQuery();
                ResultSetMetaData rsmd = rs.getMetaData();
                for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                    System.out.print(rsmd.getColumnName(i) + " (" + rsmd.getColumnTypeName(i) + ") / ");
                }
                System.out.println("");
                while (rs.next()) {
                    System.out.println("Found username " + rs.getString("USERNAME") + " name " + rs.getString("NAME") + " email " + rs.getString("EMAIL") + " passe " + rs.getString("PASSE") + " email " + rs.getInt("LOGIN_TYPE"));
                }
            }
        }
    });
}

答案 15 :(得分:0)

最简单的方法是使用投影。它可以将查询结果直接映射到接口,并且比使用SqlResultSetMapping易于实现。

示例如下:

String splitTokens = "Hello    World  this    is    a     test";

String extractTokens[] = splitTokens.split(" ", 3);
String firstString     = extractTokens[0];
String secondString    = extractTokens[1];

投影接口中的字段必须与该实体中的字段匹配。否则,字段映射可能会中断。

此外,如果您使用@Repository public interface PeopleRepository extends JpaRepository<People, Long> { @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " + "FROM people p INNER JOIN dream_people dp " + "ON p.id = dp.people_id " + "WHERE p.user_id = :userId " + "GROUP BY dp.people_id " + "ORDER BY p.name", nativeQuery = true) List<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId); @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " + "FROM people p INNER JOIN dream_people dp " + "ON p.id = dp.people_id " + "WHERE p.user_id = :userId " + "GROUP BY dp.people_id " + "ORDER BY p.name", nativeQuery = true) Page<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId, Pageable pageable); } // Interface to which result is projected public interface PeopleDTO { String getName(); Long getCount(); } 表示法,请始终定义与实体名称匹配的别名,如示例所示。

答案 16 :(得分:0)

我们已通过以下方式解决了该问题:

   //Add actual table name here in Query
    final String sqlQuery = "Select a.* from ACTORS a"
    // add your entity manager here 
    Query query = entityManager.createNativeQuery(sqlQuery,Actors.class);
    //List contains the mapped entity data.
    List<Actors> list = (List<Actors>) query.getResultList();

答案 17 :(得分:0)

我尝试了以上答案中提到的许多方法。 SQLmapper在哪里放置它非常令人困惑。非托管POJO只是一个问题。我尝试了各种方法,但是像往常一样,我得到它的一种简单方法就可以了。我正在使用hibernate-jpa-2.1。

List<TestInfo> testInfoList = factory.createNativeQuery(QueryConstants.RUNNING_TEST_INFO_QUERY)
                    .getResultList();

唯一需要注意的是POJO具有与查询相同的成员变量名称(全部使用小写字母)。显然,就像在JPQL中使用TypedQueries一样,我什至不需要告诉目标类和查询。

TestInfo.class

@Setter
@Getter
@NoArgsConstructor
@ToString
public class TestInfo {

    private String emailid;
    private Long testcount;

    public TestInfo(String emailId, Long testCount) {
        super();
        this.emailid = emailId;
        this.testcount = testCount;
    }

}

答案 18 :(得分:0)

在这种情况下,像实体一样使用“数据库视图”,即不可变实体非常容易。

普通实体

@Entity
@Table(name = "people")
data class Person(
  @Id
  val id: Long = -1,
  val firstName: String = "",
  val lastName: String? = null
)

查看实体

@Entity
@Immutable
@Subselect("""
select
    p.id,
    concat(p.first_name, ' ', p.last_name) as full_name
from people p
""")
data class PersonMin(
  @Id
  val id: Long,
  val fullName: String,
)

在任何存储库中,我们都可以创建查询函数/方法,就像:

@Query(value = "select p from PersonMin p")
fun findPeopleMinimum(pageable: Pageable): Page<PersonMin>

答案 19 :(得分:0)

如果查询不是太复杂,您可以执行以下操作。就我而言,我需要使用 H2 FT_Search 结果查询来进行另一个查询。

var ftSearchQuery = "SELECT * FROM FT_SEARCH(\'something\', 0, 0)";
List<Object[]> results = query.getResultList();
List<Model> models = new ArrayList<>();
for (Object[] result : results) {
    var newQuery = "SELECT * FROM " + (String) result[0];
    models.addAll(entityManager.createNativeQuery(newQuery, Model.class).getResultList());
  }

可能有更简洁的方法来做到这一点。

答案 20 :(得分:-1)

将SQL查询转换为POJO类集合的简单方法,

Query query = getCurrentSession().createSQLQuery(sqlQuery).addEntity(Actors.class);
List<Actors> list = (List<Actors>) query.list();
return list;

答案 21 :(得分:-1)

请参阅下面的示例,将POJO用作伪实体,以便在不使用复杂的SqlResultSetMapping的情况下从本机查询中检索结果。在你的POJO中只需要两个注释,一个裸@Enity和一个虚拟@Id。 @Id可用于您选择的任何字段,@ Id字段可以有重复键但不能为空值。

由于@Enity不映射到任何物理表,因此该POJO称为伪实体。

环境:eclipselink 2.5.0-RC1,jpa-2.1.0,mysql-connector-java-5.1.14

您可以下载完整的maven项目here

本机查询基于mysql示例员工db http://dev.mysql.com/doc/employee/en/employees-installation.html

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="jpa-mysql" transaction-type="RESOURCE_LOCAL">
    <class>org.moonwave.jpa.model.pojo.Employee</class>
    <properties>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/employees" />
        <property name="javax.persistence.jdbc.user" value="user" />
        <property name="javax.persistence.jdbc.password" value="***" />
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
    </properties>
</persistence-unit>

Employee.java

package org.moonwave.jpa.model.pojo;

@Entity
public class Employee {

@Id
protected Long empNo;

protected String firstName;
protected String lastName;
protected String title;

public Long getEmpNo() {
    return empNo;
}
public void setEmpNo(Long empNo) {
    this.empNo = empNo;
}
public String getFirstName() {
    return firstName;
}
public void setFirstName(String firstName) {
    this.firstName = firstName;
}
public String getLastName() {
    return lastName;
}
public void setLastName(String lastName) {
    this.lastName = lastName;
}   
public String getTitle() {
    return title;
}
public void setTitle(String title) {
    this.title = title;
}
public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("empNo: ").append(empNo);
    sb.append(", firstName: ").append(firstName);
    sb.append(", lastName: ").append(lastName);
    sb.append(", title: ").append(title);
    return sb.toString();
}
}

EmployeeNativeQuery.java

public class EmployeeNativeQuery {
private EntityManager em;
private EntityManagerFactory emf;

public void setUp() throws Exception {
    emf=Persistence.createEntityManagerFactory("jpa-mysql");
    em=emf.createEntityManager();
}
public void tearDown()throws Exception {
    em.close();
    emf.close();
}

@SuppressWarnings("unchecked")
public void query() {
    Query query = em.createNativeQuery("select e.emp_no as empNo, e.first_name as firstName, e.last_name as lastName," + 
            "t.title from employees e join titles t on e.emp_no = t.emp_no", Employee.class);
    query.setMaxResults(30);
    List<Employee> list = (List<Employee>) query.getResultList();
    int i = 0;
    for (Object emp : list) {
        System.out.println(++i + ": " + emp.toString());
    }
}

public static void main( String[] args ) {
    EmployeeNativeQuery test = new EmployeeNativeQuery();
    try {
        test.setUp();
        test.query();
        test.tearDown();
    } catch (Exception e) {
        System.out.println(e);
    }
}
}

答案 22 :(得分:-2)

使用DTO Design Pattern。它在EJB 2.0中使用。实体是容器管理的。 DTO Design Pattern用于解决此问题。 但是,当应用程序单独开发Server SideClient Side时,可能会立即使用它。DTO不希望传递/返回Server side时使用Entity注释为Client Side

DTO示例:

PersonEntity.java

@Entity
public class PersonEntity {
    @Id
    private String id;
    private String address;

    public PersonEntity(){

    }
    public PersonEntity(String id, String address) {
        this.id = id;
        this.address = address;
    }
    //getter and setter

}

PersonDTO.java

public class PersonDTO {
    private String id;
    private String address;

    public PersonDTO() {
    }
    public PersonDTO(String id, String address) {
        this.id = id;
        this.address = address;
    }

    //getter and setter 
}

DTOBuilder.java

public class DTOBuilder() {
    public static PersonDTO buildPersonDTO(PersonEntity person) {
        return new PersonDTO(person.getId(). person.getAddress());
    }
}

EntityBuilder.java&lt; - 它需要

public class EntityBuilder() {
    public static PersonEntity buildPersonEntity(PersonDTO person) {
        return new PersonEntity(person.getId(). person.getAddress());
    }
}