216

プロジェクトでJPAを使用しています。

5つのテーブルで結合操作を行う必要があるクエリに到達しました。そこで、5つのフィールドを返すネイティブクエリを作成しました。

次に、結果オブジェクトを、同じ5つの文字列を含むjavaPOJOクラスに変換します。

その結果をPOJOオブジェクトリストに直接キャストする方法はJPAにありますか?

私は次の解決策に到達しました..

@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クラスに変換できますか?

4

21 に答える 21

237

私はこれに対するいくつかの解決策を見つけました。

マップされたエンティティの使用(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);

@SqlResultSetMappingを使用したJPA2.1

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かなり侵襲的に追加することに気付いた人の1人であり、エンティティ内の名前付きクエリの定義が特に嫌いなので、代わりに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>

そして、それらは私が知っているすべての解決策です。最後の2つは、JPA2.1を使用できる場合の理想的な方法です。

于 2014-01-31T18:08:36.263 に答える
115

JPAは、SqlResultSetMappingネイティブクエリから返されるものをエンティティにマップできるようにするを提供しますまたはカスタムクラス

EDIT JPA 1.0では、エンティティ以外のクラスへのマッピングは許可されていません。JPA 2.1でのみ、Javaクラスの戻り値をマップするためにConstructorResultが追加されました。

また、カウントの取得に関するOPの問題については、単一の結果セットマッピングを定義するだけで十分です。ColumnResult

于 2012-10-22T14:16:00.527 に答える
12

はい、JPA2.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());
    }

それでおしまい。

于 2016-09-19T12:08:42.720 に答える
11

を使用する場合Spring-jpa、これは回答とこの質問の補足です。欠陥がある場合はこれを修正してください。私は主にObject[]、私が満たす実際的なニーズに基づいて、「結果をpojoにマッピングする」ために3つの方法を使用しました。

  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;
        }
    }
    

方法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:EdwinDalorzoの回答の例として@SqlResultSetMapping@NamedNativeQueryを使用します。Entity

最初の2つのメソッドは、カスタマイズされたコンバーターなど、多くの中間ハンドラーを呼び出します。たとえば、をAntiStealing定義しますsecretKey。永続化する前に、コンバータを挿入して暗号化します。これにより、最初の2つのメソッドが変換された結果を返しますが、secretKeyこれは私が望んでいることではありません。方法3はコンバーターを克服し、返さsecretKeyれるのは保存されているものと同じです(暗号化されたもの)。

于 2017-04-24T10:12:54.563 に答える
9

アンラップ手順を実行して、結果を非エンティティ(Beans / POJO)に割り当てることができます。手順は以下のとおりです。

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

使用法はJPA-Hibernate実装用です。

于 2018-03-26T10:24:43.680 に答える
8

最も簡単な方法は、soプロジェクションを使用することです。クエリ結果をインターフェイスに直接マップでき、SqlResultSetMappingを使用するよりも実装が簡単です。

例を以下に示します。

@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();

}

投影されたインターフェイスのフィールドは、このエンティティのフィールドと一致する必要があります。そうしないと、フィールドマッピングが機能しなくなる可能性があります。

また、表記法を使用する場合はSELECT table.column、例に示すように、エンティティの名前と一致するエイリアスを常に定義してください。

于 2019-04-03T05:17:26.787 に答える
7

Hibernateでは、このコードを使用してネイティブクエリを簡単にマッピングできます。

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;}
于 2019-04-09T12:45:00.563 に答える
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);
于 2015-05-07T20:53:27.980 に答える
4

Hibernateの使用:

@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();
}
于 2019-03-04T13:12:11.810 に答える
2

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"));
                }
            }
        }
    });
}
于 2019-03-05T15:05:12.280 に答える
2

次の方法で問題を解決しました。

   //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();
于 2019-07-08T13:38:41.203 に答える
1

他の人がすでに考えられるすべての解決策について言及しているので、私は回避策の解決策を共有しています。

私の状況では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>>() {});

他のデータベースでも同じことがわかると思います。

また、参考までに、JPA2.0ネイティブクエリの結果をマップとして

于 2017-11-11T05:18:07.873 に答える
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だけを使用することはできませんでした。

于 2018-12-18T10:49:31.750 に答える
0

複雑なSqlResultSetMappingを使用せずにネイティブクエリから結果を取得するための疑似エンティティとしてPOJOを使用する方法については、以下の例を参照してください。POJOにベア@Enityとダミー@Idの2つのアノテーションが必要です。@Idは任意のフィールドで使用でき、@ Idフィールドは重複するキーを持つことができますが、null値を持つことはできません。

@Enityは物理テーブルにマップされないため、このPOJOは疑似エンティティと呼ばれます。

環境:eclipselink 2.5.0-RC1、jpa-2.1.0、mysql-connector-java-5.1.14

ここから完全なMavenプロジェクトをダウンロードできます

ネイティブクエリは、mysqlサンプルemployeesdbhttp ://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);
    }
}
}
于 2014-12-22T06:27:02.367 に答える
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.
} 
于 2016-02-29T11:38:05.630 に答える
0

Hibernateの使用:

@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();
}
于 2019-03-04T13:17:19.803 に答える
0

上記の回答で述べたように、私は多くのことを試みました。SQLmapperは、どこに配置するかについて非常に混乱していました。管理されていないPOJOのみが問題でした。私はさまざまな方法を試していましたが、それを機能させる簡単な方法の1つはいつものことでした。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;
    }

}
于 2020-09-17T15:40:00.813 に答える
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>
于 2020-11-29T06:17:52.357 に答える
0

クエリがそれほど複雑でない場合は、次のようにすることができます。私の場合、H2FT_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());
  }

これを行うにはおそらくもっとクリーンな方法があります。

于 2021-02-08T20:03:42.403 に答える
-1

SQLクエリをPOJOクラスコレクションに変換する簡単な方法、

Query query = getCurrentSession().createSQLQuery(sqlQuery).addEntity(Actors.class);
List<Actors> list = (List<Actors>) query.list();
return list;
于 2016-09-21T07:14:46.550 に答える
-2

を使用しDTO Design Patternます。で使用されましたEJB 2.0。エンティティはコンテナ管理されていました。DTO Design Patternこの問題を解決するために使用されます。Server Sideただし、アプリケーションが個別に開発されたときに、現在使用されている可能性がありますClient Side。に注釈を付けて渡したり返したりしたくないDTO場合に使用されます。Server sideEntityClient 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<-必要な場合

public class EntityBuilder() {
    public static PersonEntity buildPersonEntity(PersonDTO person) {
        return new PersonEntity(person.getId(). person.getAddress());
    }
}
于 2012-10-22T14:00:39.893 に答える