2013年12月18日水曜日

tomcat-maven-pluginでTomcatのmanagerアプリにアクセスする際の認証情報の設定について

MavenでwarファイルをTomcatにインストールして、サーバーを再起動したりするにはtomcat-maven-pluginとTomcatのmanagerアプリの設定で可能です。そして、Tomcatのmanagerアプリにアクセスするには認証情報が必要になるのですが、これをpom.xmlファイルに書いてしまうと、Gitなどのバージョンコントロールシステムで管理するには内容が丸見えなので問題あり。そこで、どこに認証情報を書くのかというと、Mavenにはsettings.xmlとファイルがあるので、ここにサーバー情報を記述。

settings.xml

<servers>
  <server>
    <id></id>
    <username></username>
    <password></password>
  </server>
</servers>

このsettings.xmlのサーバーIDはpom.xmlのtomcat-maven-pluginのサーバー情報と紐付いてる。

2013年12月17日火曜日

Tomcatのmanagerアプリが404でアクセスできない場合

Tomcatの管理ページにアクセスしたら404が出たので、あれっ、tomcat-users.xmlを設定し忘れたかな?と思ったらそういうわけでもない。。。

いろいろ調べていたら、どうやらUbuntuはapt-get install tomcat6-adminでインストールしてあげないといけないらしい。知らんがな、、、

https://help.ubuntu.com/lts/serverguide/tomcat.html

org.hibernate.ObjectNotFoundExceptionがエンティティの@OneToOneの関連性で出てしまう場合の対処方法

Hibernateで1対1の関係にあるエンティティ(@OneToOne)がorg.hibernate.ObjectNotFoundException出てしまう場合、つまりユニークキーに紐付けられたレコードが無いよって場合の対処方法。またもやHibernateのブラックボックス、、、

@OneToOne(fetch=FetchType.EAGER)
@JoinColumn(name="A_ID")
@NotFound(action=NotFoundAction.IGNORE)

@NotFoundでIGNOREを使ってやると例外無くnullを設定してくれる。

2013年12月13日金曜日

Mavenのmaven-war-pluginのfilterとprofileで変数を設定してやれば、環境毎にwarパッケージを作成できる。

Mavenのmaven-war-pluginとprofileで変数を設定してやれば、環境毎にwarパッケージを作成できます。物凄い便利。

ポイントは、

  1. maven-war-pluginのwebResourceで環境毎に設定したい設定ファイルを列挙
  2. webResourceで列挙したファイルにfilterを使ってやる
  3. profileで環境毎のproperties変数を定義してやる
実行する時は、mvn package -P dev, mvn package -P productionみたいな感じでwarを作成できる。


http://maven.apache.org/plugins/maven-war-plugin/examples/adding-filtering-webresources.html
http://www.manydesigns.com/en/portofino/portofino3/tutorials/using-maven-profiles-and-resource-filtering
http://erhan.me/2011/10/20/property-substitution-for-web-xml-with-using-profile-properties-maven-pom-xml/

MavenでJavascriptやStylesheetのファイルはYUI compressor Maven MOJOを使う

MavenでJavascriptやStylesheetのファイルはYUI compressor Maven MOJOを使うと便利です。JSやCSSファイルをデフォルトで-minという名前で圧縮してくれるし、aggregationタグでは圧縮したファイルを一括してくれる。

http://alchim.sourceforge.net/yuicompressor-maven-plugin/index.html

ハマったところと言えば、Mavenのライフサイクルのフェーズがprepare-packageじゃないと思った順序でpom.xmlの内容が動作してくれなかった点。

2013年12月12日木曜日

HibernateのMySQL/JDBCコネクションが途切れる問題

HibernateでMySQLへの接続が1日経つと例外が発生したので、なんでかなとちょっと調べてみました。どうやらこれはMySQLのJDBCの仕様のようで、8時間経つとコネクションが途切れるようです。

http://stackoverflow.com/questions/270800/why-does-hibernate-jdbc-mysql-drop-connections-after-a-day-or-so

ただ、JDBC側でautoReconnect=trueとして自動接続をするような対処方法を取ると、コネクションを自動接続してくれるものの、例外が発生したクエリをもう1度実行してくれる訳では無いので、面倒くさい副作用が発生します。

ということで、Hibernate側でselect 1などのテストクエリを出すような対処方法を取る解決方法があるようです。hibernate.cfg.xmlでのデフォルト設定では出てこないようなプロパティなので、どこを見ればいいのか戸惑いますが、以下の通り設定できるようです。

<!--connection pool--> 
<property name="hibernate.dbcp.maxActive">10</property> 
<property name="hibernate.dbcp.whenExhaustedAction">1</property> 
<property name="hibernate.dbcp.maxWait">20000</property> 
<property name="hibernate.dbcp.maxIdle">10</property> 

<!-- prepared statement cache--> 
<property name="hibernate.dbcp.ps.maxActive">10</property> 
<property name="hibernate.dbcp.ps.whenExhaustedAction">1</property> 
<property name="hibernate.dbcp.ps.maxWait">20000</property> 
<property name="hibernate.dbcp.ps.maxIdle">10</property> 

<!-- optional query to validate pooled connections:--> 
<property name="hibernate.dbcp.validationQuery">select 1</property> 
<property name="hibernate.dbcp.testOnBorrow">true</property> 
<property name="hibernate.dbcp.testOnReturn">true</property> 

http://stackoverflow.com/questions/7766023/hibernate-failed-to-execute-query-afte-1-day
http://my.safaribooksonline.com/book/programming/java/0321268199/performance/ch10lev1sec4

2013年12月11日水曜日

Tomcat7のWeb Administrationで403エラーが出る

TomcatのWeb Administrationでtomcat-users.xmlを設定したのだが403が出る。どうやら以前と違うようだ。

<role rolename="admin"/>
<role rolename="admin-gui"/>
<role rolename="manager"/>
<role rolename="manager-gui"/>

http://stackoverflow.com/questions/11080148/403-access-denied-in-tomcat
http://tomcat.apache.org/tomcat-7.0-doc/manager-howto.html

2013年12月5日木曜日

Mavenで署名付きjarを作るにはmaven-jar-pluginとmaven-jarsigner-pluginを使う

署名付きアプレットを作るのにMavenでどうやってやればいいのかまとめてみました。まずは手順:


  1. keystoreを予め作っておく
  2. jarをおいておくフォルダを予め作っておく
  3. maven-jar-pluginでjarを作る
  4. maven-jarsigner-pluginで署名付きjarを作る

1.2.はmavenを走らせる前に予め作っておきました。3.4. はcompileのフェーズで実行。サンプルのpom.xmlは以下:

  <build>
    <plugins>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.4</version>
      <executions>
          <execution>
          <id>make-a-jar</id>
          <phase>compile</phase>
          <goals>
            <goal>jar</goal>
          </goals>
        <configuration>
           <includes>
                  <include><!-- Include files--></include>
           </includes>
          <outputDirectory><!-- Output directory --></outputDirectory>
                  <finalName><!-- jar name --></finalName>
                </configuration>
          </execution>
      </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jarsigner-plugin</artifactId>
        <version>1.2</version>
        <configuration>
          <archive><!-- jar file --></archive>
          <keystore><!-- keystore file --></keystore>
          <storepass><!-- password--></storepass>
          <alias><!-- alias --></alias>
          <verbose>true</verbose>
        </configuration>
        <executions>
          <execution>
    <id>sign-a-jar</id>
            <phase>compile</phase>
            <goals>
              <goal>sign</goal>
            </goals>
          </execution>
        </executions>
 </plugin>
   </plugins>
  </build>

http://maven.apache.org/plugins/maven-jar-plugin/usage.html
http://stackoverflow.com/questions/3598424/jar-signing-strategy-in-maven-projects
http://stackoverflow.com/questions/4757426/maven-specify-the-outputdirectory-only-for-packaging-a-jar

2013年12月3日火曜日

Springで独自のフィルターを使いたい場合

Spring Securityを使う以前に簡単にフィルターを使いたいなと思い、Springではどうやって使うのだろうと調べてみました。

http://srlawr.blogspot.com/2011/09/creating-custom-filter-in-spring.html

ミソとしては、org.springframework.web.filter.DelegatingFilterProxyに自分でカスタマイズしたFilterをbeanとして設定してやれば良いようです。このフィルタはorg.springframework.web.filter.OncePerRequestFilterを実装した例が多かったので、これを実装したけど、、、これで良いのかな??

そしてパラメーターはinit-paramで渡せるようです。

http://stackoverflow.com/questions/5807922/how-does-spring-wire-a-onceperrequestfilter-with-its-init-param-values

javax.servlet.Filterだとダメなのだろうか??動いてはいるのですが、ブラックボックスなとこがあるのでちょっと心配です。

Spring SecurityのバージョンがSpring Frameworkと違うのでかなりハマりました。

Spring Securityを使う場合、これを書いている時点では3.1.4.RELEASEが最新だったのですが、Spring Frameworkの最新バージョン(3.2.4.RELEASE)と違うんだなと何気にpom.xmlに追加してmavenを走らせたらどえらくハマりました。。。

エラーエラーの連発で、どこの何がまずいのかメッセージを見てもサッパリ。ネットでいろいろ調べてみると、やっとの事で見つけました。

http://stackoverflow.com/questions/16801639/spring-core-3-2-2-spring-security-3-1-4-java-lang-incompatibleclasschangeerro
http://www.mkyong.com/mongodb/spring-asm-dependency-issue-in-spring-data/

要するにSpring Securityの3.1.4.RELEASEはSpringの3.0.7に依存してるので、裏で読み込まれているjarが3.0.7の物がいくつかあり、これがSpring 3.2.4と喧嘩してしまっている状態。どうやらここがハマった原因だったようです。mvn dependency:treeで確認。

解決方法としては、3.0.7でなくて3.2.4を明示的に読み込ませればOK。pom.xmlのdependencyManagementタグ内で古いjarを読み込んでるパッケージを明示的に3.2.4にしてやれば見事解決しました。

なぜSpringとSpring Securityでバージョンが違うのか?
なぜSpring Securityは最新のバージョンを読み込まないのか?

ここら辺が疑問ですが、こういう類のエラーは本当にSpringの嫌なとこですね。エラーメッセージを見ても分からないし、mvn dependency:treeなんてコマンド、今回初めて知りました。

ちょっと原因らしきことが書いてあります。異なるバージョンのjarを読み込んだ場合の優先度や明示的にpom.xmlで指定する話など。解決方法としてはいいけど、その都度mvn dependency:treeで調べないといけないのか。Spring SecurityをSpringの一部にすればいいのに。。

http://www.baeldung.com/spring-security-with-maven



2013年11月23日土曜日

org.hibernate.NonUniqueObjectExceptionにもちょっとハマった

Hibernateで以下の例外が出る場合は、リレーションシップにあるエンティティ(クラス)のhashCode、equalsメソッドがどう実装されているか見直しましょう。

Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:

jQueryの:notセレクタは何かと便利

HTMLのエレメントでclassに何種類か設定してある場合、jQueryの:notセレクタを使ってやると便利。

<div class="someA someB" />

<script>
  var divs = $('.someA:not(someB)');
</script>

みたいな感じ。

MySQLの作成日と更新日のカラム生成の設定が分かりやすかった記事

MySQLのテーブルでレコードの増減が頻繁に起こるテーブルは作成日と更新日のカラムを作成したりすると便利です。ただ、コードでいちいち書くの面倒くさいからデータベース側で設定できないか調べていると便利な記事を見つけました。

ポイントは、

  • Timestamp型はレコードに更新があれば自動更新してくれる。ただし、テーブルにつき1つ。
  • 作成日カラムはDatetime型にする。
  • レコードがINSERTされたら作成日を設定してやるトリガーを用意。
こんなとこでした。あとの注意点は作成日のデフォルト値かな。


http://www.marcus-povey.co.uk/2013/03/11/automatic-create-and-modified-timestamps-in-mysql/

HibernateのAutomatic State Detection

まだちょっとsaveOrUpdateとmergeの違いを分かっていないのですが、基本的なところでsaveする時とupdateする時の違いは、エンティティのID(主キー)がnullかどうかで自動制御しているようです。ちょっと、ここもハマった。

// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catID);

// in a higher tier of the application
Cat mate = new Cat();
cat.setMate(mate);

// later, in a new session
secondSession.saveOrUpdate(cat);   // update existing state (cat has a non-null id)
secondSession.saveOrUpdate(mate);  // save the new instance (mate has a null id)


http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-saveorupdate

HTMLのhiddenを使わずして値をエレメントに保持する

HTMLのページで、例えばテーブルの列のIDなどを保持したい場合にhiddenなどのタグを使うと面倒くさいので、エレメントその物にデータ(ID)を保持できるのが便利。

DIVのdata-value属性を使ってやると、jQueryだとdata()で取得できる。


<div class="comment" data-value="64">

 var value = $('[div selector]').data('value');

楽ちん楽ちん。

jQueryでAjaxを使ったDataTableでちょっとハマったとこ

jQueryのDatableのプラグインで、Ajaxを使ってサーバーサイドからデータを取るページを作るのに若干ハマったとこをメモ書き。

ページでテーブルが表示されてから、何かのアクションを起こしてテーブルをサーバーサイドのデータで再描画する時、sEchoというパラメータに注意。あまり注意してなかったので、適当に1と設定していたのですが、これは描画リクエストがある度に更新してやらないと、クライアントサイドで再描画が起こらない。(キャッシュしてるのかな?)

という事なので、バックエンドではインクリメントをして返してやると、ちゃんとテーブルを描画してくれました。

stringsEchoAn unaltered copy of sEcho sent from the client side. This parameter will change with each draw (it is basically a draw count) - so it is important that this is implemented. Note that it strongly recommended for security reasons that you 'cast' this parameter to an integer in order to prevent Cross Site Scripting (XSS) attacks.

2013年11月21日木曜日

JPAとHibernateのCascadeTypeにハマりました。。。


Hibernateでエンティティの関連性にCascadeTypeを使うと、データ取得だけとか、更新もするとか、いろいろ指定できるはずなのですが、できない??結構ハマったのですが、いろいろと調べると参考になるサイトに、JPAとHibernateでそれぞれCascadeTypeのアノテーションがあり、HibernateのSessionを使っているとJPAのCascadeTypeでは予測した挙動で動いてくれないようです。これはハマる!!

org.hibernate.annotations.CascadeType
javax.persistence.CascadeType
は違う!!

JPA
 @OneToMany(fetch = FetchType.LAZY, 
       cascade = {CascadeType.PERSIST,CascadeType.MERGE }, 
       mappedBy = "stock")
Hibernate
@OneToMany(fetch = FetchType.LAZY, mappedBy = "stock")
@Cascade({CascadeType.SAVE_UPDATE})

それにしても、@OneToManyはjavax.persistenceで、@Cascadeはorg.hibernate.annotations、ややこしい。。。

http://docs.jboss.org/hibernate/core/3.5/javadocs/org/hibernate/annotations/CascadeType.html
http://docs.oracle.com/javaee/6/api/javax/persistence/CascadeType.html

SpringのControllerでリクエストパラメーターが多い時はMultiValueMapを使う

SpringのControllerでリクエストパラメーターをたくさん受け取る場合、org.springframework.util.MultiValueMapを使うと便利。

パラメーター(キー)がユニークな場合は、MultiValueMap<String,String>なんでgetFirst(K key)で、パラメーター(キー)に紐付けられた値が複数ある場合は、MultiValueMap<String,List<String>>をget(Object key)で取れる。

http://docs.spring.io/spring/docs/3.1.4.RELEASE/javadoc-api/org/springframework/util/MultiValueMap.html
http://stackoverflow.com/questions/16355168/spring-mvc-requestparam-as-map-get-url-array-parameters-not-working

2013年11月16日土曜日

HTMLのformをjQueryでsubmitさせない方法

<form id="someform">....</form>

<script>
  $('#someform').submit(function(event){
      event.preventDefault();
  });
</script>

event.preventDefault()はイベント制御には何かと便利。

http://api.jquery.com/event.preventDefault/


jQueryとAjaxを使ってフォームのデータを送信する時、たくさんのエレメントがあると面倒くさいのでserialize()を使う。

<form id="someForm">...</form>

<script>
  $.ajax({
      url: 'someurl',
      type: 'post',
      data: $('#someForm').serialize()
  }) ;
</script>

こんな感じ。

http://stackoverflow.com/questions/5004233/capture-all-of-the-forms-data-and-submit-it-to-a-php-script-jquery-ajax-post

JUnit4で特定のテストケースを実行しない方法

これは非常に簡単で@Testで指定したテストケースを@Ignoreで無視しておいてと教えてあげればいい。

http://junit.sourceforge.net/javadoc/org/junit/Ignore.html

HibernateのsaveOrUpdateについて

テーブルにレコードを追加、もしくは既にあるレコードを更新する場合にSessionのsaveOrUpdateを使っているのだが、INSERTかUPDATEかの挙動はプライマリーキーがテーブルに存在しているかどうかで決定されるようだ。nullであればもちろん追加される。

しかしながら、updateやsaveOrUpdateやmergeなどがあって、まだまだ違いが不明。ここは要する調査。

MySQLのselect文で連番を自動生成する方法

変数を使ってインクリメントするだけ。

mysql> set @n=0;
mysql> select @n:=@n+1 serial_number from table1;

http://stackoverflow.com/questions/15930514/mysql-auto-increment-temporary-column-in-select-statement

MySQLのselectからinsertする構文

insert into table1
select a, b, c from table2 where id=?

みたいな感じ。

http://stackoverflow.com/questions/15523597/mysql-insert-into-values-and-select

HTMLのformのエレメントを一括で無効化する方法

<fieldset></fieldset>でdisabled属性を使えば良い。

<form>
  <fieldset>
    <legend>Personalia:</legend>
    Name: <input type="text"><br>
    Email: <input type="text"><br>
    Date of birth: <input type="text">
  </fieldset>
</form>

http://www.w3schools.com/tags/tag_fieldset.asp

2013年11月15日金曜日

MySQLで外部キー制約を一時的に解除する方法

MySQLで外部キー制約を持ったテーブルの定義を変更したい場合、何かと制約でエラーが出て変更できない面倒くさい状況が出るので回避策。

> SET foreign_key_checks=0 ------> 外部キー制約を解除
> SET foreign_key_checks=1 ------> 外部キー制約を有効

http://stackoverflow.com/questions/2300396/force-drop-mysql-bypassing-foreign-key-constraint

OS Xのターミナルでカーソルを先頭、最後尾に戻すショートカット

ctrl + a -----> front
ctrl + e -----> end

http://apple.stackexchange.com/questions/8928/move-to-start-of-line-in-terminal-app

2013年11月8日金曜日

HibernateでLocalSessionFactoryBeanを複数設定した場合の使いわけ

Hibernateで複数のデータベースに接続したい場合、LocalSessionFactoryBeanを複数設定ファイルに書きますが、ソースコードのDAO側でどうやって切り分けるのかが分からない。


    <bean id="sessionFactoryA" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="configLocation">
            <value>/WEB-INF/A.cfg.xml</value>
        </property>
    </bean>

   <bean id="sessionFactoryB" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="configLocation">
            <value>/WEB-INF/B.cfg.xml</value>
        </property>

    </bean>

調べてみると、意外にも簡単で@Qualifierアノテーションでidを指定するだけでOK。

@Repository
public class SomeDaoImpl implements SomeDao
{
    @Autowired
    @Qualifier(value="sessionFactoryA")
    private SessionFactory _sessionFactory;


こんな感じ。簡単簡単。

2013年11月7日木曜日

とりあえずHibernateのエンティティマッピングの書き方をすぐ忘れてしまうので。。。

とりあえずHibernateのエンティティマッピングの書き方をすぐ忘れてしまうので、一番すっきりとしていて分かりやすいお手本のリンクをメモっておくことにした。

http://en.wikibooks.org/wiki/Java_Persistence/OneToOne

Hibernateでカラムのソートの昇順・降順を指定するには@OrderByを使う

@OrderColumnの落とし穴 でHibernateのエンティティで一対多の関係を持ったコレクションのフィールドで@OrderColumnを使用した場合に、java.util.Listがnullオブジェクトを追加してしまうのでjava.util.Setを使う事にしました。

じゃあそのコレクションのソート降順・昇順の指定はどうなるんだ?という事ですが、@OrderByで指定できるようです。中身は@OrderBy("ID ASC")もしくは@OrderBy("ID DESC")のように、ここはシンプルに指定できます。また、なぜか@OrderColumnは指定する必要が無い事に気づきました。なんで???

またもやHibernateの未知なブラックボックスです。どうやって@OrderByと@OrderColumnを使い分けるのだろう??

http://stackoverflow.com/questions/11433195/hibernate-orderby-vs-ordercolumn-to-maintain-the-order-of-a-collection

2013年11月6日水曜日

とりあえずSpring+Hibernateで、DAO(データレイヤー)をJUnit4でテストする上で分かったことをまとめた。

まだ謎が多いので、分かった事をとりあえず一覧で。


  • JUnit4で作ったクラスはAbstractTransactionalJUnit4SpringContextTestsを継承する。なぜ?
  • spring-test.jarをpom.xmlに追加
  • @RunWith(SpringJUnit4ClassRunner.class)をクラスレベルで書く。なぜ必要?
  • @ContextConfiguration(locations={classpath:applicationContext.xml, classpath:hibernate.cfg.xml})をクラスレベルで書いて、設定ファイルを読み込む。この設定ファイルはクラスパスがとおった
  • @TransactionConfiguratioをクラスレベルで書いて、defaultRollback=trueにする。ロールバック機能を使うと、データベースの状態をテスト前の状態にできるから便利。
  • public void setDataSource(DataSource dataSource)をオーバーライドする。@Resource(name="dataSource")で設定ファイルで指定されているdataSourceを指定。
とにかくハマったとこ。。。

  1. Maven+Eclipse+WTPのファイル構造で設定ファイルをsrc/main/webapp/WEB-INF/は、クラスパス上にはならないので、src/test/resourceにテスト用の設定ファイルをtest-applicationContext.xml, test-hibernate.cfg.xmlのようにコピーした。もっと賢いやり方ないのかな。。。?ただ、WEB-INFから設定ファイルは動かしたくない。
  2. setDataSourceでtest-hibernate.cfg.xmlからDBのコネクション情報を指定してあげないといけないのだが、<session-factory></session-factory>の中に一括して書いてあるので、コネクション上に関してだけ抜き出して、applicationContext.xmlでdataSourceとして書きだした。
多くに共通してるとこは、設定の仕方が多い事が仇になっているということ。それがSpringとかHibernateの分かりにくいとこなのかなと実感。


参考にしたサイト:

http://stackoverflow.com/questions/2377763/abstracttransactionaljunit4springcontexttests-cant-get-the-dao-to-find-inserte
http://zakato.sblo.jp/article/50155918.html
http://java-cauldron.blogspot.com/2012/07/writing-junit4-tests-spring-30.html
http://mvnrepository.com/artifact/org.springframework/spring-test/3.2.4.RELEASE
http://kinoushi.blogspot.com/2008/08/abstracttransactionaljunit4springcontex.html
http://stackoverflow.com/questions/17220432/failed-to-load-applicationcontext-for-junit-test-of-spring-controller
http://junit.sourceforge.net/javadoc/org/junit/Assert.html
http://intink.blogspot.com/2012/12/hibernate4spring-framework3.html
http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/testing.html#testcontext-fixture-di
http://forum.spring.io/forum/spring-projects/container/38874-transactional-junit4-controller-testing-with-multiple-datasources
http://forum.spring.io/forum/spring-projects/container/49585-how-to-get-contextconfiguration-using-web-inf-applicationcontext-xml
http://forum.spring.io/forum/spring-projects/web/97105-testing-problem-junit4-7-spring3-0-5-hibernate-3-3-2



@OrderColumnの落とし穴

@OrderColumnにハマった。。。Stackoverflowで書いてある状況と全く同じで、一対多の関連性のあるエンティティで多の方のエンティティにListを使っていると、何故かデータベースのテーブルに無いレコードがNullとしてListに入っている。????ここにハマった。

要するにListと使って多エンティティを保持すると、保持される順序を指定しないといけないので@OrderColumnを使うのだが、ここの仕様がややこしくてブラックボックス。

The order column must be of integral type. The persistence provider maintains a contiguous (non-sparse) ordering of the values of the order column when updating the association or element collection. The order column value for the first element is 0.
※contiguous=切れ目の無い

と、JavaDocを読んでててイマイチ不明なのだが、要するに@OrderColumnで指定するカラムがintの主キーで、400が一番若いIDだとすると、0~399まではテーブルには存在しないのだが、わざわざご丁寧に0~399までをnullオブジェクトとしてListの保存するわけだ。これが、contiguous (non-sparse) ordering. なんとお節介な機能だ。。。

そして、これを回避するにはList型でなくSet型を使って使うとnullオブジェクトが保持されなくなったのだが、どうもここはまだまだ奥が深そう。。。こういうところがHibernateの分かりにくいところ。。。

http://stackoverflow.com/questions/13307849/hibernate-returns-list-with-null-values-onetomany-annotation-with-list-type
http://docs.oracle.com/javaee/6/api/javax/persistence/OrderColumn.html

HibernateのFetchTypeがLAZYとEAGERの違い


2つのエンティティ(テーブル)が一対多の関連性を持つ場合、どのタイミングで多のエンティティをロードしてあげるか、FetchTypeで2通りのやり方がある。

@OneToMany(fetch=FetchType.EAGER)
@OneToMany(fetch=FetchType.LAZY)

例えば、大学(Univeristy)というエンティティと学生(Student)というエンティティが一対多で関連付けられているとすると、Listのstudentsにデータをロードするタイミングとして、他のフィールド(id, name, address)と同じタイミングでロードするEAGERと、getStudents()などのオンディマンドでゲッターを呼ぶ場合にロードするLAZYのやり方がある。

public class University {
 private String id;
 private String name;
 private String address;
 private List<Student> students;

 // setters and getters
}

使い分けるポイントとしては、studentsにどれだけのデータがロードされるか、一度に全てロードする事が得策かどうかを考える必要がある。

http://stackoverflow.com/questions/2990799/difference-between-fetchtype-lazy-and-eager-in-java-persistence

2013年10月30日水曜日

Springでページのエンコーディング設定方法

<filter>  
    <filter-name>encodingFilter</filter-name>  
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
    <init-param>  
       <param-name>encoding</param-name>  
       <param-value>UTF-8</param-value>  
    </init-param>  
    <init-param>  
       <param-name>forceEncoding</param-name>  
       <param-value>true</param-value>  
    </init-param>  

</filter>

をweb.xmlに設定すれば、エンコーディングはUTF-8で出力。

http://stackoverflow.com/questions/5928046/spring-mvc-utf-8-encoding

2013年10月25日金曜日

単一テーブル継承(Single Table Inheritance)

Hibernateの@Entityを実装している時に、RDBの特定のカラム値を元にポリモーフしたサブクラスを割り当てたい。つまり、抽象クラスを@Entityにして、サブクラスを実装するにはどうしたら良いか調べた。

あっさりとJPA仕様にやり方が書いてあるのを見つけたところ、どうやらSingle Table Inheritance(単一テーブル継承)というやり方がある事が分かった。

そのやり方をWikiから抜粋:

Single Table Inheritance[edit]

Single table inheritance is the simplest and typically the best performing and best solution. In single table inheritance a single table is used to store all of the instances of the entire inheritance hierarchy. The table will have a column for every attribute of every class in the hierarchy. A discriminator column is used to determine which class the particular row belongs to, each class in the hierarchy defines its own unique discriminator value.

Example single table inheritance table in database[edit]

PROJECT (table)
IDPROJ_TYPENAMEBUDGET
1LAccounting50000
2SLegalnull

Example single table inheritance annotations[edit]

@Entity
@Inheritance
@DiscriminatorColumn(name="PROJ_TYPE")
@Table(name="PROJECT")
public abstract class Project {
  @Id
  private long id;
  ...
}
@Entity
@DiscriminatorValue("L")
public class LargeProject extends Project {
  private BigDecimal budget;
}
@Entity
@DiscriminatorValue("S")
public class SmallProject extends Project {
}


ポイントは@DiscripnatorColumnを抽象クラスで指定して、@DiscriminatorValueを実装クラスで教えてあげる。これはかなり便利。



Spring 3.xでJSON型を返す@Controllerのクラスを実装する時に気をつけたい事

Spring 3.xで@Controllerのクラスを実装して、JSON型を返すRESTfulなサービスを作る時に気をつけたい事がある。ここは少しハマった。。。

まず仕様の抜粋から、

Underneath the covers, Spring MVC delegates to a HttpMessageConverter to perform the serialization. In this case, Spring MVC invokes a MappingJacksonHttpMessageConverter built on the Jackson JSON processor. This implementation is enabled automatically when you use the mvc:annotation-driven configuration element with Jackson present in your classpath.

つまり、Spring MVCはJSONの場合、JavaオブジェクトのシリアライズをMappingJacksonHttpMessageConverterに委譲する。その為には、applicationContext.xmlで<mvc:annotation-driven/>を追加しないと委譲が行われない。そして、これはメソッドの戻り値が@ResponseBodyで指定される。

そして、ハマったところ。。。

JSONにマップするクラスがgetter/setterを持っていない場合、HTTP 406のエラーコードが返されてうまくいかない。つまりJavaBeansでなければならないよう。おそらくMessageConverterの仕様でしょうが、ここがブラックボックスで分からない。。(?)

ということで、ここには気をつけましょう。


  1. <mvc:annotation-driven/>
  2. jackson-mapper-asl.jar, jackson-xc.jarが必要
  3. @ResponseBody
  4. JavaBeans(?)パターンの実装 -------> 調査中


http://spring.io/blog/2010/01/25/ajax-simplifications-in-spring-3-0/

2013年10月24日木曜日

jQueryでラジオボタンの無効化やチェックのやり方


$('#radioButtonId').prop('disabled', true);
$('#radioButtonId').prop('checked'true);

http://stackoverflow.com/questions/17057481/enable-disable-a-button-on-select-of-radio-button-in-jquery

jQueryのセレクタで複数のタグ属性を指定する使い方


例えば、

<div>
  <input type="radio" name="radio1" value="somevalue"/>
</div>

$('#divId input[type=radio][name=radio1]').prop('disabled', true);

こんな感じで、[]を複数使う。

http://api.jquery.com/multiple-attribute-selector/

jQueryのCDN

<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>                                                

<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>                                        
<link rel="stylesheet" type="text/css" media="all" href="http://code.jquery.com/ui/1.10.3/themes/ui-lightness/jquery-ui.css" />

jQueryのDataTablesを使うのに、どのCDNを使えば良いか?


<script type="text/javascript" src="http://datatables.net/download/build/jquery.dataTables.js"></script>                  
<link rel="stylesheet" type="text/css" media="all" href="http://code.jquery.com/ui/1.10.3/themes/ui-lightness/jquery-ui.css" />                       
<link rel="stylesheet" type="text/css" media="all" href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css" /> 

jQueryのDataTablesで各種ウィジェットを隠すには?


$('#tableId').dataTable({
    "bFilter": false,
    "bInfo": false
    "bPaginate": false

});

http://datatables.net/usage/features

jQueryのDataTablesで必要なHTMLタグの前提条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<table id="table_id">
    <thead>
        <tr>
            <th>Column 1</th>
            <th>Column 2</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Row 1 Data 1</td>
            <td>Row 1 Data 2</td>
        </tr>
        <tr>
            <td>Row 2 Data 1</td>
            <td>Row 2 Data 2</td>
        </tr>
    </tbody>
</table>

※thead, tbodyが抜けててハマる事があるので注意。

http://datatables.net/blog/Getting_started_with_DataTables%3a_First_steps