반응형

오라클에서 BLOB 정보를 가져오는 쿼리를 MyBatis를 이용해서 작성하는 경우 BLOB 정보를 Map 형태로 바로 받으면 안되며, 반드시 ResultMap으로 받아야 한다.

<resultMap type="java.util.Map" id="imgResult">
	<result column="IMG" property="IMG" javaType="[B" jdbcType="BLOB"/>
</resultMap>

Select 절에서는 resultType이 아닌 resultMap을 이용해서 imgResult로 설정해야 한다.

<select id="select_img" parameterType="java.util.Map" resultMap="imgResult">
	select img from img_table where id = #{id}
</select>

이렇게 가져온 이미지를 컨트롤 단에서 사용 방법은 아래와 같다.

Map<String, Object> imgMap = imageService.select_img(map);
byte[] arr = (byte[]) imgMap.get("IMG");

String base64Encode = null;
if (arr != null && arr.length > 0) {
	base64Encode = byteToBase64(arr);
    base64Encode = "data:image/png;base64," + base64Encode;
}

private static String byteToBase64(byte[] arr) {
	String result = "";
    
    try {
    	result = Base64Utils.encodeToString(arr);
    } catch (Exception e) {
    	e.printStackTrace();
    }
    return result;
}

이렇게 가져온 base64Encode 의 값을 JSP 또는 HTML의 img 태그에 src로 할당하면 이미지를 브라우저에서 바로 볼 수 있게 된다.

반응형

'Java 기반 Web > Java' 카테고리의 다른 글

MyBatis 에서 어의 없는 오류..ㅠㅠ  (0) 2022.05.28
반응형

jquery datepicker를 이용해서 년월만 선택하고 싶을 때가 있다.
이때 유용하게 사용할 수 있는 방법이다.
활용성을 높이기 위해 공통 js파일에 show_calendar_month라는 Function을 정의해서 사용했다. 이렇게 이용을 하면 사용하고자 하는 페이지에서 보다 유연하게 사용할 수 있다.
input 파라미터로는 선택한 년월을 표기할 textbox의 id를 넣어 주면 된다.
년월 picker 기능은 모두 Function에 정의해 두고 호출만 하면 된다.

function show_calendar_month(obj) {
	$("#" + obj).datepicker({
		monthNames: [ "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월" ],
		monthNamesShort: [ "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월" ],
        changeMonth: true,
        changeYear: true,
        showButtonPanel: true,
        dateFormat: 'yy-mm',
        onChangeMonthYear: function (year, month, inst) {
        	$(this).val($.datepicker.formatDate('yy-mm', new Date(year, month - 1, 1)));
    	},
        onClose: function(dateText, inst) { 
            var month = $("#ui-datepicker-div .ui-datepicker-month :selected").val();
            var year = $("#ui-datepicker-div .ui-datepicker-year :selected").val();
            $(this).datepicker('setDate', new Date(year, month, 1));
        },
        beforeShow : function(input, inst) {
            if ((datestr = $(this).val()).length > 0) {
                actDate = datestr.split('-');
                year = actDate[0];
                month = actDate[1]-1;
                $(this).datepicker('option', 'defaultDate', new Date(year, month));
                $(this).datepicker('setDate', new Date(year, month));
            }
        }
    });
    
    $("#" + obj).focus(function () {
        $(".ui-datepicker-calendar").hide();
    });
    
    $('#' + obj).datepicker('show');
}

이렇게 정의한 Function을 html/jsp 파일에서 아래와 같이 호출만 하면 된다.

...
<td class="c" width="250px">
	<input type=text id="Fdate1" name="Fdate1" value='<cnsone:date value="${Fdate1}"/>' readonly style="width:70px;text-align:center;">
	<input type='button' onClick="show_calendar_month('Fdate1');" style="background:url(${WEBROOT}/images/icon/calendar.gif);border:0;width:16px;height:18px;cursor:hand;vertical-align:middle;">
</td>
...

스타일 시트를 추가해서 기존에 보이던 일자를 보이지 않도록 처리한다.
<style>
table.ui-datepicker-calendar { display:none; }
</style>
달력 아이콘 버튼을 클릭하면 아래의 이미지와 같이 년월 picker의 모습을 보게 된다.
년과 월만을 선택하는 UI를 datepicker를 이용해서 간단하게 만들 수 있다.

그림1 - 년월 Picker
반응형
반응형

MyBatis 사용 도중 아래와 같은 오류 메시지 발생.

도대체 뭐가 문제일까?

처음엔 아래와 같은 오류로 인해 상당히 혼란 스러웠다.

뭐가 문제지??

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.NumberFormatException: For input string: "N"
### Cause: java.lang.NumberFormatException: For input string: "N"

 

실제 이 오류를 발생한 xml파일 내의 쿼리는 아래와 같다.

다이나믹 쿼리 수행을 위해 추가한 if 절로 인해 발생하는 것이었다. 문법 상의 문제가 없는지 여러번 살폈으나 별다른 이상을 발견하지 못했고, 구글링 도중 발견한 글 중 하나가 바깥에 표기한 큰따옴표(")를 작은따옴표(')로 변경해 보라는 글을 발견했다. 

<select id="select_CuttingAndNoCutting" resultMap="CuttingResult" parameterType="java.util.Map">
		SELECT  cutting_date, nvl(cut, 0) as cut, nvl(nocut, 0) as nocut 
		  FROM ( select cutting_date, sum(order_length) as order_length, cutting_type 
				   from ( SELECT cutting_date, order_length, cutting_type 
							from cutting_order_circuit
						   where cutting_date like #{YYYYMM,jdbcType=VARCHAR} || '%'
						     and drum_no not like '%결품%' 
							 and drum_no is not null 

							<if test="isPowerCutter == 'Y'">  
							 and (actor = #{actor,jdbcType=VARCHAR}
							  or actor is null 
							 and powerorder = 'on')  
							 and powercomplete is null
							</if>
						
							<if test="isPowerCutter == 'N'">  
							 and actor = #{actor,jdbcType=VARCHAR}
							</if>
						
						) group by cutting_date, cutting_type
			   ) PIVOT ( sum(order_length) FOR cutting_type IN ('절단' as cut, '미절단' as nocut))       
		order by cutting_date
	</select>

혹시나 하는 마음에 큰따옴표와 작은따옴표의 위치를 변경한 결과 아무런 문제 없이 내가 예상했던 대로 쿼리가 수행되는 것이었다.

정말 어의없는 상황..이 문제로 상당한 시간을 허비했거늘...

오늘도 이렇게 어의없이 문제를 깔끔하게(?) 해결한 하루 였다.

내가 바꾼 건 따옴표 밖에는 없었다는..

<select id="select_CuttingAndNoCutting" resultMap="CuttingResult" parameterType="java.util.Map">
		SELECT  cutting_date, nvl(cut, 0) as cut, nvl(nocut, 0) as nocut 
		  FROM ( select cutting_date, sum(order_length) as order_length, cutting_type 
				   from ( SELECT cutting_date, order_length, cutting_type 
							from cutting_order_circuit
						   where cutting_date like #{YYYYMM,jdbcType=VARCHAR} || '%'
						     and drum_no not like '%결품%' 
							 and drum_no is not null 

							<if test='isPowerCutter == "Y"'>  
							 and (actor = #{actor,jdbcType=VARCHAR}
							  or actor is null 
							 and powerorder = 'on')  
							 and powercomplete is null
							</if>
						
							<if test='isPowerCutter == "N"'>
							 and actor = #{actor,jdbcType=VARCHAR}
							</if>
						
						) group by cutting_date, cutting_type
			   ) PIVOT ( sum(order_length) FOR cutting_type IN ('절단' as cut, '미절단' as nocut))       
		order by cutting_date
반응형

'Java 기반 Web > Java' 카테고리의 다른 글

오라클 DB에서 BLOB 정보를 가져와서 보여주기  (0) 2022.07.20
반응형

오늘 택배로 도착한 포맥스.


스피커를 고정할 7.9센치 직경의 구멍을 2개 뚫고 순간 접착제로 포맥스를 붙이면서 스피커의 외형을 만듭니다.
내부에 블루투스 앰프 모둘을 중앙에 위치시키고 전원 연결을 위한 구멍을 뒷부분에 만듭니다.
스피커의 빈 공간에 울림이 생기면 소리가 울리는 현상이 생기기에 솜으로 소리를 흡수하기 위해 솜으로 양옆, 하단, 상단을 덮어 줍니다.
스피커 유닛 뒤에서 발생하는 잡소리가 내부에서 울리지 않고 흡수되어 전면의 스피커 소리가 방해받지 않도록 하면 됩니다.


완성된 스피커의 모습입니다.
소리도 나쁘지 않고, 소리를 가장 작게 했는데도 소리가 생각보다 크네요.
소리도 시원하게 나오고, 첫 시도지만 그럭저럭 맘에 드네요.


반응형

'IT제품' 카테고리의 다른 글

블루투스 스피커 만들기 (1/2)  (0) 2022.04.30
굿노트용 2022년 Calendar 일정관리  (0) 2021.11.27
애플워치 SE 개봉기  (0) 2020.11.30
아이폰12 프로 개봉기  (0) 2020.11.12
반응형

당근에서 스피커유닛과 함께 구매한 tda7492p 블루투스 앰프를 12V 5A 어댑터로 연결해서 만들었습니다.
스피커 유닛은 중국산 완음 4인치 풀레인지 입니다.
선을 스피커의 +/- 맞게 연결하고, tda7492p 앰프 모듈의 +/- 에 맞게 잘 연결하고 어답터를 연결 하면 끝입니다.
앰프 전원 연결 후 켜고 폰의 블루투스 설정화면으로 가서 SANWU Audio가 보이며, 이 녀석을 선택하면 연결이 완료됩니다.
케이스를 만들지 않은 상태에서도 내 귀에는 꽤 괜찮은 소리를 들려주는 것 같네요.
케이스를 씌우고 튜닝한 후의 소리가 긍금해지네요.
다음엔 케이스까지 씌워서 완성된 모습을 올려 보도록 하겠습니다.

반응형

'IT제품' 카테고리의 다른 글

블루투스 스피커 만들기 (2/2)  (0) 2022.04.30
굿노트용 2022년 Calendar 일정관리  (0) 2021.11.27
애플워치 SE 개봉기  (0) 2020.11.30
아이폰12 프로 개봉기  (0) 2020.11.12
반응형

Window를 상속해 클래스를 정의하는 것도 가능하다.

다음 예제는 세 개의 클래스가 있고, 세 개의 소스 코드 파일이 있다. 

[InheritAppAndWindow.cs]

Main에서 MyApplication 타입의 객체를 생성하고, 이 객체의 Run을 호출한다.

using System;
using System.Windows;
using System.Windows.Input;

namespace InheritAppAndWindow
{
    public class InheritAppAndWindow
    {
        [STAThread]
        public static void Main()
        {
            MyApplication app = new MyApplication();
            app.Run();
        }
    }
}

[MyApplication.cs]

OnStartup 메소드를 오버라이딩한 부분에서 MyWindow 타입의 객체를 생성하고 있다.

using System;
using System.Windows;
using System.Windows.Input;

namespace InheritAppAndWindow
{
    public class MyApplication : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            MyWindow win = new MyWindow();
            win.Show();
        }
    }
}

[MyWindow.cs]

Window를 상속받는 클래스는 일반적으로 생성자에서 그 클래스를 초기화한다. 예제에서는 Title 프로퍼티만 초기화한다. 프로퍼티 이름 앞에 객체의 이름을 따로 쓰지 않았는데, MyWindow가 Window를 상속받기 때문이다.

using System;
using System.Windows;
using System.Windows.Input;

namespace InheritAppAndWindow
{
    public class MyWindow : Window
    {
        public MyWindow()
        {
           this.Title = "Inherit App & Window";
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);

            string strMessage = string.Format("Window clicked with {0} button at point ({1})", e.ChangedButton, e.GetPosition(this));
            MessageBox.Show(strMessage, Title);
        }
    }
}

 

InheritAppAndWindow.zip
0.02MB

반응형
반응형

명령 행 인자는 문자열의 배열 형태로 Main에 전달된다. 이 문자열의 배열은 OnStartUp 메소드에서도 사용할 수 있다. StartupEventArgs 인자의 Args 프로퍼티를 참조하면 된다.

Application에 MainWindow란 이름의 프로퍼티가 있다는 것은 프로그램이 여러 개의 창을 가질 수 있음을 시사하고 있는데, 이는 사실이다. 대화 상자를 그 좋은 예로 들 수 있다. 대화 상자는 기본적으로 Window 객체이지만 표시 방식이 조금 다르다는 점과 사용자와 상호작용을 한다는 점에서 약간의 차이가 있다.

 

다음 프로그램은 몇 개의 창을 더 만드는  프로그램이다. 마치 여러 개의 창을 초대해 파티를 여는 것 같아서 이름을 ThrowWindowParty로 했다.

using System;
using System.Windows;
using System.Windows.Input;

namespace ThrowWindowParty
{
    public class ThrowWinowParty : Application
    {
        [STAThread]
        public static void Main()
        {
            ThrowWinowParty app = new ThrowWinowParty();
            //app.ShutdownMode = ShutdownMode.OnMainWindowClose;
            app.Run();

        }

        protected override void OnStartup(StartupEventArgs e)
        {
            //메인 창이 닫힐 때만 Run이 반환되고, 프로그램이 종료된다.
            ShutdownMode = ShutdownMode.OnMainWindowClose;

            Window winMain = new Window();
            winMain.Title = "Main Window";
            winMain.MouseDown += WindowOnMouseDown;
            winMain.Show();

            for (int i = 0; i < 2; i++)
            {
                Window win = new Window();
                win.Title = "Extra Window No. " + (i + 1);
                //세 개의 윈도우 모두 화면 하단부에 있는 윈도우의 작업 표시줄에 나타나지 않도록 설정.
                win.ShowInTaskbar = false;
                //MainWindow = win;
                win.Owner = winMain;
                win.Show();
            }
        }

        private void WindowOnMouseDown(object sender, MouseButtonEventArgs e)
        {
            Window win = new Window();
            win.Title = "Modal Dialog Box";
            win.ShowDialog();
        }
    }
}

ThrowWindowParty.zip
0.02MB

반응형
반응형
//사용자가 선택한 ComboBox의 Index값을 이용해서 Value 값을 가져온다.

var prop = cboTime.Items[cboTime.SelectedIndex].GetType().GetProperty(cboTime.ValueMember);
Time = prop.GetValue(cboTime.Items[cboTime.SelectedIndex], null).ToString();

C#을 이용해서 WinForm 개발을 하다 보면 ComboBox 컨트롤 사용을 자주 하게 된다.
매번 ComboBox를 사용하면서 특정 값 또는 텍스트로 ComboBox의 목록 중 1개를 선택하고자 할 경우가 많다.
다양한 방법이 있겠지만, 간단하게 구현해서 사용할 수 있는 방법을 소개하고자 한다.

ComboBox를 이용해서 선택할 수 있는 시간을 콤보박스에 보여주기 위해 Items에 추가하는 로직과 특정 시간대의 값에 따라 콤보박스가 선택되어져 있도록 하기 위한 코드를 남겨둔다.

 

아래는 ComboBox에 간단하게 DisplayMember와 ValueMember로 구분해서 Items에 추가하는 방법.

cboTime.DisplayMember = "Text";
cboTime.ValueMember = "Value";
cboTime.Items.Add(new { Text = "09:00", Value = "0900" });
cboTime.Items.Add(new { Text = "09:30", Value = "0930" });
cboTime.Items.Add(new { Text = "10:00", Value = "1000" });
cboTime.Items.Add(new { Text = "13:30", Value = "1330" });
cboTime.Items.Add(new { Text = "14:00", Value = "1400" });
cboTime.Items.Add(new { Text = "14:30", Value = "1430" });

 

아래는 사용자가 입력한 값에 따라 ComboBox가 선택되어져 있도록 하는 방법

string Time = "1000";
//Time 값이 비어 있을 경우에는 첫번째 항목이 선택되도록 처리
if (string.IsNullOrEmpty(Time) || string.IsNullOrWhiteSpace(Time)) cboTime.SelectedIndex = 0;
else
{
    //ComboBox 항목 수 만큼 돌면서 Time 변수와 같은 값을 가진 항목을 검색
    for(int i = 0; i < cboTime.Items.Count; i++)
    {
        var prop = cboTime.Items[i].GetType().GetProperty(cboTime.ValueMember);
        if (prop != null && prop.GetValue(cboTime.Items[i], null).ToString() == Time)
        {
            cboTime.SelectedIndex = i;
            break;
        }
    }
}

 

사용자가 ComboBox에서 특정 값을 선택했을 경우 가져오는 방법

//사용자가 선택한 ComboBox의 Index값을 이용해서 value을 가져온다.
var prop = cboTime.Items[cboTime.SelectedIndex].GetType().GetProperty(cboTime.ValueMember);
Time = prop.GetValue(cboTime.Items[cboTime.SelectedIndex], null).ToString();

 

반응형
반응형

아이패드에서 굿노트를 사용하다 2022년 일정관리 Calendar를 만들어 보았다.

나만 사용하기 위해 만든 일정계획이다 보니 약간은 허접하기도 한데..

나에 꼭 필요한 기능 중심으로 만들어 본 것이다.

 

월간 달력 화면 - 월간 계획을 작성하고 표현하는 영역입니다.

아래의 주차 표시 부분을 클릭하면 주간 계획을 세울 수 있는 화면으로 이동합니다.

 

주간 일정 계획을 세울 수 있는 화면입니다.

 

별 모양의 아이콘을 선택하면 이동하게 되는 2022년 전체 달력 입니다.

다이야몬드 모양의 아이콘을 클릭하면 이동하게 되는 2022년 연간 계획 화면입니다.

맨 마지막 장에 있는 노트양식 입니다.

계속해서 추가해서 사용할 수 있는 노트입니다.

2022_Diary.pdf
0.67MB

 

필요하신 분들은 언제든 가져가서 사용하시면 됩니다.

사용하시면서 제안 또는 오류가 있으면 댓글로 알려주시면 감사하겠습니다.

반응형

'IT제품' 카테고리의 다른 글

블루투스 스피커 만들기 (2/2)  (0) 2022.04.30
블루투스 스피커 만들기 (1/2)  (0) 2022.04.30
애플워치 SE 개봉기  (0) 2020.11.30
아이폰12 프로 개봉기  (0) 2020.11.12
반응형

프로그램에서 Application 클래스를 상속받아 프로그램 종료 시 프로그램 종료 여부를 확인하는 팝업 창을 보여주는 예제인 듯 하다.

제공된 예제를 실행했으나, 오버라이딩한 OnSessionEnding 메소드가 호출되지 못하고 있다.

내가 잘못 알고 있는 것일 수도 있는데..혹 OnSessionEnding 메소드가 호출되기 위한 조건이나 방법을 아시는 분이 있으시면 댓글로 알려 주셨으면 합니다.

제가 책을 읽으며 테스트 했던 소스는 아래와 같습니다.

using System;
using System.Windows;
using System.Windows.Input;

namespace InheritTheApp
{
    public class InheritTheApp : Application
    {
        [STAThread]
        public static void Main()
        {
            InheritTheApp app = new InheritTheApp();
            app.Run();
        }

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            Window win = new Window();
            win.Title = "Inherit the App";
            win.Show();
        }

        protected override void OnSessionEnding(SessionEndingCancelEventArgs e)
        {
            base.OnSessionEnding(e);

            MessageBoxResult result = MessageBox.Show("Do you want to save your data?", 
            	MainWindow.Title, MessageBoxButton.YesNoCancel, MessageBoxImage.Question, 
                MessageBoxResult.Yes);

            e.Cancel = (result == MessageBoxResult.Cancel);
        }

        protected override void OnExit(ExitEventArgs e)
        {
            MessageBox.Show("Application이 종료됩니다.");
            base.OnExit(e);
        }
    }
}

InheritTheApp.zip
0.01MB

반응형

+ Recent posts