Unsupported major.minor version 52.0 [Java]
FilerException: Attempt to recreate a file for type [Java]
Listからremoveするための正しい実装 [Java]
JavaでListからremove()する際には、equals()をオーバーライドしないと正しい挙動をしない可能性があるという書き込みを見つけました。
これはひとつの変数に、2回以上newして作成したインスタンス格納した場合に注意すべき内容です。
Listにデータを詰めるときには、for文の中でよくこのパターンをやりますよね。
そもそもインスタンス作成の考えをきっちり抑えていないと、この過ちを犯すことになります。私も言われてみて、そりゃそうだと膝を叩きました。
一つの変数を使いまわしても、都度インスタンス生成すればどんどん新たな空間が割り当てられるわけです。equals()をオーバーライドしないでのremove()は本当の削除対象と合致しているか、曖昧になっているわけです。
そこで明示的にマッチさせるため。equals()をオーバーライドするわけです。
public boolean equals(Object o) {
if(o instanceof TargetClass) {
return this.name.equals(((TargetClass)o).name);
} else {
return false;
}
}
案外見逃してそう。
Junitでprivateメソッドをてすとする [Java]
テストしたいコード
public class Hoge() {
private String find(String a, int b) {
:
return result;
}
}
これに対するテストコードはこんな感じ。
Hoge hoge = new Hoge();
Method method = Hoge.class.getDeclaredMethod("find", String.class, int.class);
method.setAccessible(true);
String actual = (String)method.invoke(hoge, "key", 2);
デバッグで追っていくとちゃんとfindが呼び出されている。
しかしこのprivateメソッド内で@EJBのJPAを呼び出しているのでが、ここで例外発生。
java.lang.reflect.InvocationTargetException
調査継続中です。
メソッド名を取得する [Java]
以前にも同じような記事を書いたが、絞り込んで再投稿。
ログ出力する際に行番号はlogbackなどの機能で取得できるが、メソッド名取得まではサポートされていない。
ソース上に情報取得処理を埋め込むことにする。
■クラス名取得
パッケージ名を含むクラス名
getClass().getName();
クラス名のみ
getClass().getSimpleName()
■スタックトレースから各種情報を取得
拡張子(.java)付きファイル名
Thread.currentThread().getStackTrace()[1].getFileName();
パッケージ名を含むクラス名
Thread.currentThread().getStackTrace()[1].getClassName();
メソッド名
Thread.currentThread().getStackTrace()[1].getMethodName();
行番号
Thread.currentThread().getStackTrace()[1].getLineNumber();
FileSystems.getDefault()で戻されるパス [Java]
nio2を利用するので、まずはパスの生成。
FileSystem fs = FileSystems.getDefault();
Path path = fs.getPath("sample.xml");
この時のデフォルトパスはどこかというと、glassfish対象ドメイン下のconfigになる。
こんな感じ。
c:\GlassFish_Server\glassfish\domains\domain1\config
これはこれでありだけど、configファイルじゃないので、ここにファイルを置くのは気持ち悪い。
パス変更についてはまたそのうちに。
JPA removeなのにupdateも実行 [Java]
エンティティ自体はNetBeansによるDBからの自動作成。
アクセサもNetBeansによるエンティティからの自動作成。
【実行ログ】
[EL Fine]: sql: 2015-11-12 16:19:53.308--ClientSession(16435676)--Connection(1434252175)--UPDATE user_table SET USER_NAME = ?, USER_PWD = ? WHERE (UID = ?)
bind => [3 parameters bound]
[EL Fine]: sql: 2015-11-12 16:19:53.308--ClientSession(16435676)--Connection(1434252175)--DELETE FROM user_table WHERE (UID = ?)
【エンティティ】
@Entity
@Table(name = "user_table")
@XmlRootElement
:
public class UserTable implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "UID")
private Integer uid;
@Size(max = 64)
@Column(name = "USER_NAME")
private String userName;
:
【アクセサ呼出し箇所】
@Stateless
public class UserLogic {
@EJB
private UserTableFacade userTableFacade;
public void deleteData() {
UserTable ut = new UserTable();
ut.setUid = 1;
:
userTableFacade.remove(ut);
※このメソッドを呼び出す側でトランザクション管理。
エンティティ・クラスの設定のような気がするが、調査する時間的猶予がないため、delete文を自作してEntityManager#createNativeQuery()、Query#executeUpdate()で一旦逃れることにした。
JPA insert時例外(必須項目未設定) [Java]
ポイント
■ConstraintViolationExceptionが発生する。
なんとなく「その他のエラー」っぽいですが、必須項目未設定時にも発生します。
エラーの詳細はこんな感じ。
ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=uid, rootBeanClass=class entity.UserMaster, messageTemplate='{javax.validation.constraints.NotNull.message}'}
もう一段階踏み込んだ例外があるといいんですけど。
JPA insert時例外(重複エラー) [Java]
insert時の重複エラーについて、試行錯誤中です。
ポイント
■persistence.xmlにオプションを追加しないと例外が発生しない
<property name="eclipselink.validate-existence" value="true"/>
■発生する例外はEntityExistsExceptionでは例外が発生しない。
EntityManager#persist()で EntityExistsExceptionが発生。
とりあえずinsertはこれでいけそうですが、delete時にデータがなくても例外が発生しない模様。
現在persistence.xmlのオプションを調査中です。
対象がないと事前にfind()しなきゃいけないし、隙間もできるんで気持ち悪いなぁ。
JPA カラム名とエンティティ属性名の大文字/小文字記述ミス防止 [Java]
persistence.xmlに以下のオプションを追加します。
<property name="eclipselink.jpa.uppercase-column-names" value="true"/>
できればエンティティクラスは自動生成したほうがいいですよね。