発表用資料の作成
PowerPointのテンプレートをコピーして使用する。
\\kgakusei1\share\澤田\発表資料.pptx
チーム開発の感想などは、Backlogで担当した課題を見れば思い出しやすい。
Webアプリの講義内容と関連資料など
PowerPointのテンプレートをコピーして使用する。
\\kgakusei1\share\澤田\発表資料.pptx
チーム開発の感想などは、Backlogで担当した課題を見れば思い出しやすい。
基本機能が動作するようにがんばりましょう!
機能の単位はロバストネス図で考えること。
発表用のパワポ作成の課題を誰かに割り当てる
(テンプレートを用意するので必要事項を記入する)
発表する機能の動作確認。
1現目はチーム内でパワポの確認とデモ内容の確認。
2現目は発表。
たとえばidをURLに含める場合のJSP記述方法。
<a href="hoge?id=${obj.id}">${obj.title}</a>
ログアウトを実行したい場合、spring-security.xml に以下の設定をする。
<sec:http auto-config="true"> <intercept-url pattern="/**" access="ROLE_USER" /> <sec:form-login login-page="/login.jsp" default-target-url="/home" authentication-failure-handler-ref="authenticationFailureHandler" /> <sec:logout logout-url="/logout" logout-success-url="/" invalidate-session="true" delete-cookies="JSESSIONID" /> </sec:http> <beans:bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler"> <beans:property name="defaultFailureUrl" value="/login.jsp?error=true"/> <beans:property name="useForward" value="true"/> </beans:bean>
ログインしたユーザーを取得するには、コントローラの引数に Principal を追加する。
ここでは、追加した Princical から getName()メソッドでユーザー名を取得し、addAttribute() で name に値を設定している。
@RequestMapping(value = "/home", method = RequestMethod.GET) public String home(Model model, Principal p) { model.addAttribute("name", p.getName()); return "home"; }
Userインスタンスの取得
Principal から取得できるのは名前だけなので、詳細な情報を取得するには、名前をキーにしてUsersテーブルから取得する必要がある。
Usersテーブルから名前をキーにして取得するために、DAOにメソッド定義 findByName() を追加する。
UserDao.java
public interface UserDao<T> { public List<T> getAll(); public T findById(long id); public T findByName(String name); public void add(T data); public void update(T data); public void delete(T data); public void delete(long id); }
UserDaoImpl で、検索機能を実装する。
UserDaoImpl.java
public class UserDaoImpl implements UserDao<User> { private static EntityManagerFactory factory = Persistence.createEntityManagerFactory("persistenceUnit"); public List<User> getAll() { EntityManager manager = factory.createEntityManager(); CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User.class); Root<User> root = query.from(User.class); query.select(root); List<User> list = null; try { list = manager.createQuery(query).getResultList(); } catch (NoResultException e) { // } return list; } public User findById(long id) { EntityManager manager = factory.createEntityManager(); CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User.class); Root<User> root = query.from(User.class); query.select(root).where(builder.equal(root.get("id"), id)); User u = null; try { u = manager.createQuery(query).getSingleResult(); } catch (NoResultException e) { // } return u; } public User findByName(String name) { EntityManager manager = factory.createEntityManager(); CriteriaBuilder builder = manager.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User.class); Root<User> root = query.from(User.class); query.select(root).where(builder.equal(root.get("name"), name)); User u = null; try { u = manager.createQuery(query).getSingleResult(); } catch (NoResultException e) { // } return u; } public void add(User user) { EntityManager manager = factory.createEntityManager(); EntityTransaction transaction = manager.getTransaction(); transaction.begin(); User u = findById(user.getId()); if (u == null) { try { manager.persist(user); transaction.commit(); } catch (PersistenceException e) { transaction.rollback(); } manager.close(); } else { throw new PersistenceException("Duplicate user-id : " + u.getId()); } } public void update(User user) { EntityManager manager = factory.createEntityManager(); EntityTransaction transaction = manager.getTransaction(); transaction.begin(); try { manager.merge(user); transaction.commit(); } catch (PersistenceException e) { transaction.rollback(); } manager.close(); } public void delete(User user) { EntityManager manager = factory.createEntityManager(); EntityTransaction transaction = manager.getTransaction(); transaction.begin(); try { manager.remove(user); transaction.commit(); } catch (PersistenceException e) { transaction.rollback(); } manager.close(); } public void delete(long id) { delete(findById(id)); } }
などなど。
エンティティに対して1対多の関係を持たせる場合は、@OneToMany と @ManyToOne のアノテーションを利用する。
MyData と MsgData を連携させた例はこちら。→ http://abc2015.satoshis.jp/?p=288
基本機能だけは動作するように実装を急ぎましょう!
以下の設定を行い、ダウンロードしたJavaScriptファイルのエラーを無視するようにする。
共有データベースを配置するパソコンを決める。
そのパソコンで、server.properties を作成する。
作成する場所は、C:\Users\se3\db\hsqldb-2.3.2\hsqldb\data フォルダ。
server.properties
# Hsqldb Server cfg file. # See the HyperSQL Network Listeners chapter of the HyperSQL User Guide. # Each server.database.X setting defines a database "catalog". # I.e., an independent set of data. # Each server.database.X setting corresponds exactly to the jdbc:hsqldb:* # JDBC URL you would use if you wanted to get a direct (In-Process) # Connection to the catalog instead of "serving" it. server.database.0=file:db0/mydatabase server.dbname.0=mydatabase # I suggest that, for every file: catalog you define, you add the # connection property "ifexists=true" after the database instance # is created (which happens simply by starting the Server one time). # Just append ";ifexists=true" to the file: URL, like so: # server.database.0=file:db0/db0;ifexists=true # server.dbname.0 defaults to "" (i.e. server.dbname.n for n==0), but # the catalog definition n will be entirely ignored for n > 0 if you do not # set server.dbname.n. I.e. dbname setting is required for n > 0, though it # may be set to blank (e.g. "server.dbname.3=")
C:\Users\se3\db\hsqldb-2.3.2\hsqldb\bin にある、runServer.bat をダブルクリックして起動する。
コマンドプロンプトに次の出力があれば、データベースの作成に成功している。
C:\Users\se3\db\hsqldb-2.3.2\hsqldb\bin>cd ..\data [Server@24d46ca6]: [Thread[main,5,main]]: checkRunning(false) entered [Server@24d46ca6]: [Thread[main,5,main]]: checkRunning(false) exited [Server@24d46ca6]: Startup sequence initiated from main() method [Server@24d46ca6]: Loaded properties from [C:\Users\se3\db\hsqldb-2.3.2\hsqldb\data\server.properties] [Server@24d46ca6]: Initiating startup sequence... [Server@24d46ca6]: Server socket opened successfully in 15 ms. [Server@24d46ca6]: Database [index=0, id=0, db=file:db0/mydatabase, alias=mydata base] opened sucessfully in 484 ms. [Server@24d46ca6]: Startup sequence completed in 499 ms. [Server@24d46ca6]: 2015-11-16 11:12:14.474 HSQLDB server 2.3.2 is online on port 9001 [Server@24d46ca6]: To close normally, connect and execute SHUTDOWN SQL [Server@24d46ca6]: From command line, use [Ctrl]+[C] to abort abruptly
C:\Users\se3\db\hsqldb-2.3.2\hsqldb\bin にある、runManager.bat をダブルクリックして起動する。
接続のために以下の設定をして、OKすると接続できる。
Type : HSQL Database Engine Server URL : jdbc:hsqldb:hsql://localhost/mydatabase
他のパソコンから接続するには、パソコンのIPアドレスを調べる必要がある。
コマンドプロンプトを起動して ipconfig コマンドを実行して、IPアドレスを調べる。
C:\Users\se3>ipconfig Windows IP 構成 Wireless LAN adapter ワイヤレス ネットワーク接続: メディアの状態. . . . . . . . . . : メディアは接続されていません 接続固有の DNS サフィックス . . . : イーサネット アダプター ローカル エリア接続 2: 接続固有の DNS サフィックス . . . : IPv4 アドレス . . . . . . . . . . : 172.25.20.23 サブネット マスク . . . . . . . . : 255.255.0.0 デフォルト ゲートウェイ . . . . . : 172.25.1.254 イーサネット アダプター ローカル エリア接続 3: 接続固有の DNS サフィックス . . . : IPv4 アドレス . . . . . . . . . . : 192.168.56.1 サブネット マスク . . . . . . . . : 255.255.255.0 デフォルト ゲートウェイ . . . . . :
他のパソコンから接続する場合は、localhost の代わりにそのパソコンのIPアドレスを指定する。
C:\Users\se3\db\hsqldb-2.3.2\hsqldb\bin にある、runManager.bat をダブルクリックして起動する。
接続のために以下の設定をして、OKすると接続できる。
Type : HSQL Database Engine Server URL : jdbc:hsqldb:hsql://192.168.56.1/mydatabase
Onwerが複数のChildを持つ場合は、以下のようにエンティティを作成する。
Owner.java
@Entity public class Onwer { @Id @GeneratedValue(strategy = GenerationType.AUTO) @NutNull public long id; @OneToMany(cascade=CascadeType.ALL) @Column(nullable = false) private List<Child> children; // gettere/setter を用意 }
Child.java
@Entity public class Child { @Id @GeneratedValue(strategy = GenerationType.AUTO) @NutNull public long id; @ManyToOne @Column(nullable = false) private Owner owner; // getter/setter を用意 }
Onwerに複数のChildを追加した状態でエンティティを永続化すると、そのOwnerをDBから取り出したときは、追加した複数のChildが追加された状態で取り出せる。
課題をなかなか完了できない場合は、課題を細かく分割する。
XxControllerを作成する。
XxControllerにURL=/hoge の GET リクエストを実装する。
hoge.jsp を作成する。
XxControllerのURL=/hoge の応答で、hoge.jsp を表示する。
XxControllerのURL=/hoge の GET リクエストで message データを設定する。
hoge.jsp で message データを表示する。
hoge.jsp に form を追加する。
XxControllerにURL /hoge の POST リクエストを実装する。
XxControllerのURL=/hoge の POST リクエストの応答で resp.jsp を表示する。
機能を検討するときは、必要最小限の機能を先に作る。
たとえば、編集や削除を行う場合に、編集内容や削除の確認があったほうがいいと思った場合、まずは確認を行わないUIを作成する。
課題は以下のように作成する。
確認しないUIで作成して動かしてみる。
実際に使ってみて、確認が必要だと思ったら確認のUIを追加する。