zoukankan      html  css  js  c++  java
  • SAStruts/S2JDBC ネストしたプロパティの画面部品

    SAStruts/S2JDBC JSPで画面部品を作ってみる - 130単位

    の続きです。

    実際に作りたかった画面部品は、テーブル結合を伴った、ネストしたプロパティを持つ項目でした。これを実現するのにまた地味に時間を食いました。というか要はMapの使い方を知らなかっただけなのですが。

    エンティティとサービス

    従業員に部署を結合して、所属する部署を表示させたいとします。

    Employeeへ関連を定義します。

    @Entity
    public class Employee {
        ...
        @ManyToOne
        Department department;
    }
    

    EmployeeServiceで、結合して取得するようにします。findAll()をオーバーライドしてます。

    public class EmployeeService extends AbstractService<Employee> {
        ...
        @Override
        public List<Employee> findAll() {
            return select()
                .innerJoin(department())
                .orderBy(asc(id()))
                .getResultList();
    }
    

    JSP

    さて、前回ようなJSPに単に追加しただけでは、ネストしたプロパティアクセスしようとするとエラーが起きます。

    <html:option value="${e.jgjycd}">${e.id} ${e.name} (${e.department.name})</html:option>
    
    javax.el.PropertyNotFoundException: Property 'name' not found on type test.entity.Department
    

    employeeはBeanMapになっていても、departmentがBeanMapではないためです。employeeのみにBeans#createAndCopy()を実行しただけでは、departmentというプロパティはできなくなっているようです。ひがさんの少し前の記事にも、「ネストしたプロパティは対象外」と書かれています。

    そこで、employeeをMapに詰め替えてListを構築する際に、departmentも同様にMapにしてやる必要があります。Mapに値を追加するには、「put(key, value)」を使います。

    <%
        /* インポート等省略 */
        List<Employee> employeeList = employeeService.findAll();
        List<BeanMap> employeeItems = new ArrayList<BeanMap>();
    
        for (Employee employee : employeeList) {
            BeanMap empMap = Beans.createAndCopy(BeanMap.class, employee).execute();
            BeanMap deptMap = Beans.createAndCopy(BeanMap.class, employee.department).execute();
    
            empMap.put("department", deptMap);
            employeeItems.add(empMap);
        }
    %>
    <html:select property="searchLectureCd">
        <html:option value=""></html:option>
        <c:forEach var="e" items="${jgyofpItems}">
        <html:option value="${e.jgjycd}">${e.id}  ${e.name} (${e.department.name})</html:option>
        </c:forEach>
    </html:select>
    
    ちなみに

    最初は下記のようにやろうとしてました。

    empMap.department = deptMap;
    

    もろにPHP(の連想配列)の影響なわけですが、これではダメですね。

    サービスでMap取得 (失敗例)

    そもそも「最初からサービスでMapを返せばいいんじゃないの」と思い、以下を試してみました。

    public class EmployeeService extends AbstractService<Employee> {
        ...
        public List<BeanMap> findAllMap() {
            return jdbcManager
                .from(BeanMap.class)
                .orderBy(asc(id()))
                .getResultList();
        }
    }
    

    しかし結果は失敗。問い合わせ実行時に例外が発生します。

    org.seasar.extension.jdbc.exception.NonEntityRuntimeException: [ESSR0704](org.seasar.framework.beans.util.BeanMap)はエンティティではありません。
    

    Eclipse上ではエラーになりませんでしたし、SQLによる照会のselectBySql()だとMapで返せるようなので、いけるかと思ったのですが。AbstractServiceのジェネリクスでエンティティが指定されているのが関係してそうですが、今の自分の知識量ではこのくらいの推測が限界です。

    というわけで、素直にJSPでMapに詰め替える方法を用いることにしました。

  • 相关阅读:
    使用 BinToHex() 把 TBytes 转换为十六进制字符串 回复 "梧桐栖凤" 的问题
    ASP.NET中UrlEncode应该用Uri.EscapeDataString()
    抛弃WebService,在.NET4中用 jQuery 调用 WCF
    事实证明Ajax的世界更需要ASP.NET MVC
    tinyMCEPopup.close轻松让IE 9 RC崩溃
    不走寻常路:在WebForm中使用MVC
    关于ASP.NET预编译
    不错的VS2010扩展——JSEnhancements,让js和css也折叠
    VS2010 SP1 Beta与VisualSVN的冲突引起VS2010关闭时重启
    Web应用架构探索笔记 —— 查询
  • 原文地址:https://www.cnblogs.com/aggavara/p/2708712.html
Copyright © 2011-2022 走看看