javaメモ
ヒープ利用の確認 jenkinsとかmaven使ってるときに調べて使ってた。 1 jstat -gc `pidof java` jstat - Java 仮想マシン統計データ監視ツール docs.oracle.com
ヒープ利用の確認 jenkinsとかmaven使ってるときに調べて使ってた。 1 jstat -gc `pidof java` jstat - Java 仮想マシン統計データ監視ツール docs.oracle.com
jenkinsでmaven操作することがあった。 そのコマンド類のまとめ。 インストール 1 2 mvn clean install -Dmaven.test.skip=true -f xxx/pom.xml mvn clean install -DskipTests=TRUE -Dmaven.test.failure.ignore=true デプロイ 1 mvn deploy -Dmaven.test.skip=true -f xxx/pom.xml データロード 1 mvn deploy -Ddba.url=jdbc:oracle:thin:@sv-ora19:1521/orclpdb -Ddba.adminuser=system -Ddba.adminPassword=xxx -P dba-load process-sources -f yyy/pom.xml カバレッジとテスト 1 mvn -Dppp.url=jdbc:oracle:thin:@oracle:thin:@sv-ora19:1521/orclpdb -f /var/jenkins_home/workspace/qqq/pom.xml -Dmaven.test.failure.ignore=true -P development,coverage test -DfailIfNoTests=false '-Dtest=**,*Test' '-Dinclude.jacoco**/*' -Dloggers.SQL.level=DEBUG チェックスタイル集計 1 mvn checkstyle:check -f /var/jenkins_home/workspace/qqq/pom.xml spotbugs集計 1 mvn spotbugs:spotbugs -f /var/jenkins_home/workspace/qqq/pom.xml 暗号化パスワードを作成 1 2 3 4 5 mvn --encrypt-master-password boo {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} mvn --encrypt-password boo {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
OSやアプリケーションには更新プログラムが提供される。 windows updateとかセキュリティアップデートとか。 そういうのはライフサイクルで管理されてて、1つずつ調べないといけないときめっちゃ面倒。 それを一括で公開してくれてるサイトがある。 集約サイト Home | endoflife.date endoflife.date いつそのバージョンを公開して、あとどれぐらいサポート期間が残ってるのかを見せてくれるから、いつ頃バージョンアップ計画せなあかんのかを考えられる。 さっき見たらmacOS13が出てたし、知らん間に次のlinuxカーネルとかあるんやなぁとか、mariadbにもLTSってあるんやって気づく。 聴いたことないアプリやミドルウェアもあったりするけど簡単な説明がついてて、djangoとかグラフつきでサポート期間を見せてくれてるものもあるからわかりやすい。 ソフトウェア公開している人たちが書式とかファイル名のルール守って公開してくれてないことがあるかもしれんけど、本家サイトへのリンクがついてるからちゃんと調べるきっかけになる。 バージョンについて firefoxもchromeもメジャーバージョンをガンガン上げてくる。 バージョン番号が100超えてるのってどうなんやろ。 google cloud使うときのコマンドラインはGoogle Cloud SDKってあるんやけど、さっき見たらバージョンが387ってなってた。 そうかといえばtomcatだと、7年前がバージョン9、2年ぐらい前からバージョン10。 見た目とか機能とか大きく変更したら、整数部分のメジャーバージョン上げたらええんやけど、そうでもないことのほうが多い。 期待させといて、それほど大きく変わってなかったら「なんやねん、そんだけかいな」ってなる。
3か月の並行運用期間と過去データで検算 php版を最初に作ったときは、excelで検算してた。 webページをそのままexcelに貼り付けるだけじゃうまく行かない箇所は電卓。 今回は3月にdjango版がだいたいできたから、4月から入力しながら処理誤りを修正しつつ、php版の結果と比べてった。 処理をそろえて作ってるから当たり前なんやけど、1円単位で合計があったときはやっぱり嬉しい。 こういうとき ディスプレイが3枚 あるとチェックがめっちゃ楽。 入力は3か月やけど、帳簿は7年分を確認してった。 django版はちょっと細かめに計算。 その計算結果を使ってグラフ作らせたら、これまたパーセンテージが一致。 小数点第2位まで一致。 7年分見たとき、この数字が一致したときの快感はなんとも言えず気持ちよかった。 印刷でアセった 検索結果一覧画面を表示させておいて、これをpdf保管したい。 例えば現金出納帳は決まった年数保管しとかないといけない。 firefoxで見たら、なんじゃこりゃ。 ボタンとかロゴとかだけ表示されてるけど、数字があらへん。 cssのせい? djangoの中の何か設定? pipでなんかインストールいるんか? 小一時間ほどdjangoで印刷っていうのを調べたら、いろいろ結果が出てきた。 けっこう面倒くさい。 こんなんやってられへんし、もっと楽にできへんのかなぁってfirefox閉じてchromeで表示させたら、あっさり表示できた。 ブラウザ依存とか困るなぁ。 何年か前に「閉じる」のボタンを作ってたら、セキュリティか何かの都合でfirefoxもchromeも閉じてくれんようになった。 最近はjava scriptの解釈が変わったんかもしれんけど、また閉じれるようになった。 この印刷も何年かしたらちゃんと見えなくなるんとちゃうか。 フォームの箇所いらんから結果だけ印刷したいけど、まぁ数字は読めるしええか。 今年はいったんこれで完成。 どっかで解決方法見つけたら、pdf出力の方法探そっと。 1年かけて得られたもの php版の帳簿管理の仕組みから脱却してdjangoで動かそうとしたのが去年の今頃。 「pythonで扱うdjangoってどんなんやねん」から始まって、ssl利用とかpdfのデータベース保存とかグラフ作成とか、いろいろ挑戦してようやく完成。 google cloudの中のコンテナも用意できて、ローカルの開発環境とクラウドの本番環境を切り替えながら使うのもできるようになった。 コンテナ仮想化使ってるから、単純にアプリケーション作るための知識を得るだけじゃなく、アプリケーションインフラ寄りの知見も得られた。 日本語フォントのインストールとか、円グラフのライブラリをdjangoで使えるようにするのは苦労したなぁ。 djangoのモジュールのgitグラフを見ると、作って楽しかった履歴が見える。 できたつもりが、できてなかったり、思い出したら人に言えない恥ずかしいコミットもある。 最初はurls.py小さかったけど、こんなにデカなってた。 画面遷移がうまく行かんなぁって、コレ書き間違えてるのに気づくの時間かかったっけ。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 urlpatterns = [ path('login/', auth_views.LoginView.as_view(template_name='gvisWebApp/login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(template_name='gvisWebApp/logout.html'), name='logout'), path('home/', gvis_base_views.home, name="home"), path('gvis_001_IntraIchiran/', gvis_base_views.gvis_001_IntraIchiran, name="gvis_001_IntraIchiran"), path('gvis_002_LogKensaku/', gvis_log_views.GvisLogList.as_view(), name="gvis_002_LogKensaku"), path('gvis_Complete/', gvis_base_views.gvis_Complete, name="gvis_Complete"), path('gvis_100_ShisanKensaku/', gvis_zaiko_views.GvisZaikoList.as_view(), name="gvis_100_ShisanKensaku"), path('gvis_101_ShisanDetail/<int:pk>/', gvis_zaiko_views.GvisZaikoDetail.as_view(), name="gvis_101_ShisanDetail"), path('gvis_102_ShisanCreate/', gvis_zaiko_views.GvisZaikoCreate.as_view(), name="gvis_102_ShisanCreate"), path('gvis_103_ShisanDelete/<int:pk>/', gvis_zaiko_views.GvisZaikoDelete.as_view(), name="gvis_103_ShisanDelete"), path('gvis_104_ShisanUpdate/<int:pk>/', gvis_zaiko_views.GvisZaikoUpdate.as_view(), name="gvis_104_ShisanUpdate"), path('gvis_105_GvisZaikoTENPU/<int:pk>/', gvis_zaiko_views.GvisZaikoTENPU.as_view(), name="gvis_105_GvisZaikoTENPU"), path('gvis_200_KokyakuKensaku/', gvis_cust_views.GvisMstCustomerList.as_view(), name="gvis_200_KokyakuKensaku"), path('gvis_201_KokyakuDetail/<int:pk>/', gvis_cust_views.GvisMstCustomerDetail.as_view(), name="gvis_201_KokyakuDetail"), path('gvis_202_KokyakuCreate/', gvis_cust_views.GvisMstCustomerCreate.as_view(), name="gvis_202_KokyakuCreate"), path('gvis_203_KokyakuDelete/<int:pk>/', gvis_cust_views.GvisMstCustomerDelete.as_view(), name="gvis_203_KokyakuDelete"), path('gvis_204_KokyakuUpdate/<int:pk>/', gvis_cust_views.GvisMstCustomerUpdate.as_view(), name="gvis_204_KokyakuUpdate"), path('gvis_205_GvisCustTENPU/<int:pk>/', gvis_cust_views.GvisMstCustomerTENPU.as_view(), name="gvis_205_GvisCustTENPU"), path('gvis_300_TorihikiKensaku/', gvis_tran_views.GvisTransactionList.as_view(), name="gvis_300_TorihikiKensaku"), path('gvis_301_TorihikiDetail/<int:pk>/', gvis_tran_views.GvisTransactionDetail.as_view(), name="gvis_301_TorihikiDetail"), path('gvis_302_TorihikiCreate/', gvis_tran_views.GvisTransactionCreate.as_view(), name="gvis_302_TorihikiCreate"), path('gvis_303_TorihikiDelete/<int:pk>/', gvis_tran_views.GvisTransactionDelete.as_view(), name="gvis_303_TorihikiDelete"), path('gvis_304_TorihikiUpdate/<int:pk>/', gvis_tran_views.GvisTransactionUpdate.as_view(), name="gvis_304_TorihikiUpdate"), path('gvis_305_GvisTranTENPU/<int:pk>/', gvis_tran_views.GvisTransactionTENPU.as_view(), name="gvis_305_GvisTranTENPU"), path('gvis_400_KatsudoKensaku/', gvis_work_views.GvisWorkList.as_view(), name="gvis_400_KatsudoKensaku"), path('gvis_401_KatsudoDetail/<int:pk>/', gvis_work_views.GvisWorkDetail.as_view(), name="gvis_401_KatsudoDetail"), path('gvis_402_KatsudoCreate/', gvis_work_views.GvisWorkCreate.as_view(), name="gvis_402_KatsudoCreate"), path('gvis_403_KatsudoDelete/<int:pk>/', gvis_work_views.GvisWorkDelete.as_view(), name="gvis_403_KatsudoDelete"), path('gvis_404_KatsudoUpdate/<int:pk>/', gvis_work_views.GvisWorkUpdate.as_view(), name="gvis_404_KatsudoUpdate"), path('gvis_405_GvisWorkTENPU/<int:pk>/', gvis_work_views.GvisWorkTENPU.as_view(), name="gvis_405_GvisWorkTENPU"), path('GvisWorkCopy/', gvis_work_views.GvisWorkCopy, name="GvisWorkCopy"), path('GvisWorkMonthlyCopy/', gvis_work_views.GvisWorkMonthlyCopy, name="GvisWorkMonthlyCopy"), path('gvis_500_KeihiKensaku/', gvis_keihi_views.GvisKeihiList.as_view(), name="gvis_500_KeihiKensaku"), path('gvis_501_KeihiDetail/<int:pk>/', gvis_keihi_views.GvisKeihiDetail.as_view(), name="gvis_501_KeihiDetail"), path('gvis_502_KeihiCreate/', gvis_keihi_views.GvisKeihiCreate.as_view(), name="gvis_502_KeihiCreate"), path('gvis_503_KeihiDelete/<int:pk>/', gvis_keihi_views.GvisKeihiDelete.as_view(), name="gvis_503_KeihiDelete"), path('gvis_504_KeihiUpdate/<int:pk>/', gvis_keihi_views.GvisKeihiUpdate.as_view(), name="gvis_504_KeihiUpdate"), path('GvisKeihiCopy/', gvis_keihi_views.GvisKeihiCopy, name="GvisKeihiCopy"), path('GvisKeihiMonthlyCopy/', gvis_keihi_views.GvisKeihiMonthlyCopy, name="GvisKeihiMonthlyCopy"), path('gvis_510_KamokuKensaku/', gvis_kamoku_views.GvisKamokuList.as_view(), name="gvis_510_KamokuKensaku"), ## 科目画面ではcreate/detail viewを扱わず、削除と更新のみ path('gvis_513_KamokuDelete/<int:pk>/', gvis_kamoku_views.GvisKamokuDelete.as_view(), name="gvis_513_KamokuDelete"), path('gvis_514_KamokuUpdate/<int:pk>/', gvis_kamoku_views.GvisKamokuUpdate.as_view(), name="gvis_514_KamokuUpdate"), path('GvisKamokuCopy/', gvis_kamoku_views.GvisKamokuCopy, name="GvisKamokuCopy"), path('gvis_600_ChoboKensaku/', gvis_chobo_views.GvisChoboList.as_view(), name="gvis_600_ChoboKensaku"), path('gvis_700_KoteishisanKensaku/', gvis_koteishisan_views.GvisKoteishisanList.as_view(), name="gvis_700_KoteishisanKensaku"), path('gvis_800_GenkinKensaku/', gvis_genkin_views.GvisGenkinList.as_view(), name="gvis_800_GenkinKensaku"), path('gvis_900_ShiwakeKensaku/', gvis_shiwake_views.GvisShiwakeList.as_view(), name="gvis_900_ShiwakeKensaku"), path('ENplot/<int:year>', gvis_chobo_views.get_ENpng, name='ENplot') # 円グラフを描くための設定 数年したらまたpython&djangoの環境から脱却して別の実装へ引っ越すかもしれんけど、別の言語へ引っ越すための勉強になった。 ...
集計処理やっと作るところまで来た。 最初の頃に グラフ作れるかなって やってのたと、 集計 を組み合わせる。 結論 テストデータはこんな感じ。 月単位で経費を計上したレコードがある。 見た目ほぼそのままdockerコンテナであるmariadbのテーブル上でレコードとして存在する。 これを、縦軸に科目、横軸に月として、その1年の金額と比率を集計させる。 今月売上なんぼ、機材なんぼ、新聞図書費なんぼとかわかる。 帳簿の一部としてwebページをpdfにして保管するから、グラフはそのとき省く様ためグラフ表示のスイッチをつけとく。 さらに集計結果を円グラフ表示させる。 今月は旅費かかったなーとか、交際費もう少し使っても大丈夫かなーとか目安がわかる。 現行php版での処理をdjangoで全部作り直したとき、過去7年分の経費レコードに対する金額合計が1円の差異もなく集計・表示されたときは嬉しかった。 あと少しでphpのdockerコンテナとおさらばできる。 科目単位の集計 今までのdjango作りこみは実在するテーブルに対応したモデルだけを扱ってきた。 今回は複数テーブルから読み込んだ結果を集計するモデルを作っていく。 「見せ方」を先に考えるから、そのためのモデルをまずは準備して次にテンプレートを準備してく。 modelsの準備 結局は科目の一覧なので、ベースは科目のマスタ(GVIS_mst_kamoku)。 そこに、月単位の合計を肉付けしてモデルを作る。 1月から12月までの列を用意して、経費テーブル(GvisKeihi)の中にある科目で集計するメソッドを定義する。 以下、帳簿の一部であるGvisChobo.pyのモデル定義。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 from django.db import models from django.utils import timezone from pymysql import NULL from datetime import datetime ## 日付取得のため from datetime import date, timedelta ## マスターテーブル使うため from gvisWebApp.models.GvisMaster import GvisMstKeihishubetsu,GvisMstKamoku from gvisWebApp.models.GvisKeihi import GvisKeihi ## マスターテーブル絞り込みのため from django.db.models import Q,Sum class GvisChobo(models.Model): kamokuno = models.IntegerField(verbose_name='科目No',db_column='kamokuNo') # Field name made lowercase. def __str__(self): return str(self.kamokuno) kamokuname = models.CharField(verbose_name='科目名',db_column='kamokuName',max_length=20) # Field name made lowercase. def __str__(self): return self.kamokuname kamokusetsumei = models.CharField(verbose_name='科目説明',db_column='kamokuSetsumei', max_length=200) # Field name made lowercase. def __str__(self): return self.kamokusetsumei hyojiorder = models.IntegerField(db_column='hyojiOrder') # Field name made lowercase. def __str__(self): return str(self.hyojiorder) keihitaisho = models.IntegerField(db_column='keihiTaisho') # Field name made lowercase. def __str__(self): return str(self.keihitaisho) def get_kng01(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,1,1),date(year,2,1) - timedelta(days=1)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng def get_kng02(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,2,1),date(year,3,1) - timedelta(days=1)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng : (中略) : def get_kng12(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,12,1),date(year,12,31)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng def get_KamokuTotal(self,year): object_list = GvisKeihi.objects.filter(workperiod__range = [date(year,1,1),date(year,12,31)]) findkey = '%03d' % self.kamokuno + '-' + self.kamokuname p = object_list.filter(Q(kamoku=findkey)).aggregate(sum=Sum('kng'))['sum'] kng = 0 if p is None else p return kng class Meta: managed = False db_table = 'GVIS_mst_kamoku' 例えばget_kng12はフォームで受け取った年で、12月の科目を集計してる。経費テーブルには「003-研究開発費」みたいな感じで、科目の頭に3桁の数字とハイフンが入っているから、それをキーにしてfilterしてる。 ...