Sql Server Express

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <property name="hibernate.connection.url">jdbc:sqlserver://localhost\SQLEXPRESS;databaseName=master;user=sa;password=password</property>
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
    </session-factory>
</hibernate-configuration>

Oracle DB

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="hibernate.connection.password">manager</property>
        <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
        <property name="hibernate.connection.username">system</property>
        <property name="hibernate.default_schema">system</property>
        <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
    </session-factory>
</hibernate-configuration>
 

MySQL DB

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost/mydb</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
    </session-factory>
</hibernate-configuration>
 

 

 

 

 

MIS 發表在 痞客邦 留言(0) 人氣()

Step 01: 準備 table : TEST_GROUP & TEST_MEMBERS

 

table : TEST_GROUP

CREATE TABLE JAPPS.TEST_GROUP
(
  ID    VARCHAR2(10 BYTE),
  NAME  VARCHAR2(10 BYTE)
)

 

table :  JAPPS.TEST_MEMBERS

CREATE TABLE JAPPS.TEST_MEMBERS
(
  GID   VARCHAR2(10 BYTE),
  ID    VARCHAR2(10 BYTE),
  NAME  VARCHAR2(10 BYTE)
)

 

Step 02 : JAVA 程式段的作法

註:

1. EntityManager 的 getTransaction().begin();   不支援 //Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT

2. 使用 JpaTransactionManager 搭配 TransactionStatus 來控制

3. 只要作 JpaTransactionManager 的 commit(status) , 在 catch 中判斷  if (!status.isCompleted()) 作  baseService.getTxmBpm().rollback(status); 

package com.bpm;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.Session;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.bpm.dao.japps.TestGroupDao;
import com.bpm.dao.japps.TestMembersDao;
import com.bpm.model.japps.TestGroup;
import com.bpm.model.japps.TestMembers;
import com.bpm.model.japps.TestMembersId;
import com.util.services.BaseService;

public class SingleMultiTable {
    private static final long serialVersionUID = 1L;
    private static final Logger logger = LogManager.getLogger(SingleMultiTable.class);
    
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        testSingleTable();
        testMultiTable();
    }

    public static void testSingleTable(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-demo-cfg.xml");
        BaseService baseService = ctx.getBean("baseService",BaseService.class);
        TestGroupDao testGroupDao = ctx.getBean("testGroupDao", TestGroupDao.class);
        
        try {
            TestGroup testGroup = new TestGroup();
            testGroup.setId("A");
            testGroup.setName("Group 2");
            testGroupDao.save(testGroup);
            
            //testGroupDao.delete(testGroup);
        } catch (Exception e) {
            System.out.println("寫入資料庫有錯");
        }
        
    }
    
    public static void testMultiTable(){
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-demo-cfg.xml");
        BaseService baseService = ctx.getBean("baseService",BaseService.class);
        TestGroupDao testGroupDao = ctx.getBean("testGroupDao", TestGroupDao.class);
        TestMembersDao testMembersDao  = ctx.getBean("testMembersDao", TestMembersDao.class);
        
        TestGroup testGroup = new TestGroup();
        TestMembers testMembers = new TestMembers();
        TestMembersId testMembersId = new TestMembersId();
        
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();        
        def.setName("rootTransaction");        
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = baseService.getTxmBpm().getTransaction(def);        
        try {            
            testGroup.setId("3");
            testGroup.setName("C");
            testGroupDao.save(testGroup);
            int a;
            a = 1/0;
            testMembersId.setGid("3");
            testMembersId.setId("1");
            testMembers.setId(testMembersId);
            testMembers.setName("G3U2-2");            
            testMembersDao.save(testMembers);
            baseService.getTxmBpm().commit(status);
            
        } catch (Exception e) {
            //Session session = baseService.getSfBpmDS().getCurrentSession();
            if (!status.isCompleted()){                
                baseService.getTxmBpm().rollback(status);
            }            
            System.out.println("寫入資料庫有錯");                        
        }
        
    }

    
}


文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

使用 EasyUI 的 Datagrid 選擇到一筆記錄後,將這一筆完整的資料要送到後端 Java 接收,可以先轉換成 JSON 的格式再後送。

UI 的圖示如下,可以用 FireBug 去查看 JavaScript 裡的資料

datagrid

 

作法如下:

HTML 的 Java Script Code:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@    taglib prefix="i" uri="/esayui-tags" %>

<i:html title="easyui-datagrid & EasyUI Demo" >

<div class="col-sm-1"></div>
<div class="col-sm-10">
<i:form id="fmEmpIDLogin" action="Login"  method="post" isExtraPara="false">
                
                    <input name="reqCode" value="" type="hidden" />

    <table id="dg" class="easyui-datagrid" title="CheckBox Selection on DataGrid" style="width:100%;height:400px;padding:10px;"
            data-options="url:'Login_multiEmpID?reqCode=EmpIDList',method:'get',rownumbers:true,pagination:true,singleSelect:true,toolbar: '#tb'">
        <thead>
            <tr>
                <th data-options="field:'ck',checkbox:true"></th>
                <th data-options="field:'empId',sortable:true"> <s:property value="getText('display.sc004.empid')"/> </th>
                <th data-options="field:'realName',sortable:true"> <s:property value="getText('display.sc004.alternatename')"/> </th>
                <th data-options="field:'companyName',sortable:true"> <s:property value="getText('display.sc006.name')"/> </th>
                <th data-options="field:'deptName',sortable:true"> <s:property value="getText('display.sc007.name')"/> </th>
                <th data-options="field:'deptsManagerId',hidden:true">MANAGER_ID</th>
                <th data-options="field:'userId',hidden:true">USER_ID</th>
            </tr>
        </thead>
    </table>

    <div id="tb" style="height:auto">
        <a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true" onclick="submitForm()">Submit</a>
    </div>

</i:form>
</div>
<div class="col-sm-1"></div>
</i:html>

<script type="text/javascript">
    function submitForm(){
        $("#fmEmpIDLogin input[name='reqCode']").val("empIdLogin");
        var rowData = $('#dg').datagrid('getSelected');
        var cellRow = $("<input>").attr("type", "hidden").attr("name", "cellRow").val(JSON.stringify(rowData));
        $('#fmEmpIDLogin').append($(cellRow));
        $('#fmEmpIDLogin').submit();       
    }    
</script>

 

Java Code: 利用 String[] cellRow 接收,並用 Gson().fromJson(cellRow[0], Map.class); 作轉換即可

public class LoginAction extends BaseSupport {
    
    private String[] cellRow;    

    public String empIdLogin() throws Exception {
        String loginResult=SUCCESS;
        Userinfo userInfo = null;
        logger.debug(cellRow[0]);
        Map<String,Object> result = new Gson().fromJson(cellRow[0], Map.class);
        
        String userEmpID = result.get("empId") == null ? "" : result.get("empId").toString();
        
        return loginResult;
    }
        

    public String[] getCellRow() {
        return cellRow;
    }

    public void setCellRow(String[] cellRow) {
        this.cellRow = cellRow;
    }

}
文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

Struts2 的 logger 是與 log4j2 作整合,同樣是 Apache Project 專案之一。為了瞭解一下與架構 Java 專案時的偵錯機制,所以花了半天的時間來實作。

Maven 對 log4j2 相依性

    <properties>
        <struts2.version>2.3.24.1</struts2.version>
        <log4j2.version>2.2</log4j2.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>${log4j2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>${log4j2.version}</version>
        </dependency>

 

 log4j2.xml (在 src/main/resources 目錄下)

<?xml version="1.0" encoding="UTF-8"?>

<!-- 優先等級: FATAL > ERROR > WARN >INFO > DEBUG -->
<Configuration>
    <properties>  
        <property name="LOG_HOME">/log/mis</property>
        <property name="FILE_NAME">mis</property>    
    </properties>  
    <Appenders>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
        </Console>
        <File name="FILE" fileName="${LOG_HOME}/logfile_fileMode.log" append="true">
            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
        </File>
        <RollingRandomAccessFile name="MIS_PROJECT"
            fileName="${LOG_HOME}/${FILE_NAME}.log"
            filePattern="${LOG_HOME}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log.gz">
            
            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
            <Policies>
                <TimeBasedTriggeringPolicy />
                <SizeBasedTriggeringPolicy size="10 MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingRandomAccessFile>
        
    </Appenders>
    <Loggers>
        <Logger name="com.opensymphony.xwork2" level="info"/>
        <Logger name="org.apache.struts2" level="info"/>
        
        <Logger name="com.mis.demo" level="DEBUG" additivity="true">
            <AppenderRef ref="STDOUT"/>
        </Logger>

        <Root level="info">
            <AppenderRef ref="STDOUT"/>                  
        </Root>      
        <Root level="WARN">
            <AppenderRef ref="MIS_PROJECT" />
        </Root>        
    </Loggers>
</Configuration>

參數說明

1. monitorInterval="1800" 指 log4j2 每隔1800秒(半小時),自動監控該設定檔是否有變化,如果變化,則自動根據檔內容重新配置(很不錯的功能!)

2. RollingRandomAccessFile  即表示以檔方式記錄,注意一下 filePattern 的設置,它與 SizeBasedTriggeringPolicy (表示單個檔最大多少容量)結合在一起,非常有用,以這段配置為例,當單個文件達到10M後,會自動將以前的內容,先創建類似 2014-09(年-月)的目錄,然後按 "xxx-年-月-日-序號"命名,打成壓縮包(很體貼的設計,即省了空間,又不丟失以前的日誌資訊)

3. DefaultRolloverStrategy max="20"表示壓縮包,最多保留20個

4. 定義了一個 <Logger name="com.mis.demo" level="DEBUG" additivity="true"> ,使用 Console 方式來觀察日誌,additivity="true" 這裡注意一下,因為下面還有一個root logger,任何其它的logger最終都相當於繼承自root logger。

所以<Root level="WARN"> 這個 root logger中,記錄了 WARN 以上級別的日誌,會寫入日誌 mis.log 檔案內;當 <Logger name="com.mis.demo" level="DEBUG" additivity="true"> 有 DEBUG 以上級別的日誌時,也會寫入檔案日誌 mis.log 檔案內。。如果把additivity="true" 中的true,改成false,root logger就不會再起作用,即只會控制台輸出,日誌不會記錄在檔案中。

 

程式 Log4j2Example.java

package com.mis.demo;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Log4j2Example {

    private static final Logger LOG = LogManager.getLogger(Log4j2Example.class.getName());
    public static void main(String[] args) {
        LOG.debug("This will be printed on debug");        
        LOG.info("This will be printed on info");
        LOG.warn("This will be printed on warn");
        LOG.error("This will be printed on error");
        LOG.fatal("This will be printed on fatal");

        LOG.info("Appending string: {}.", "Hello, World");

    }

}

 

 輸出的格式內容

2016-03-11 10:43:52,260 DEBUG [main] demo.Log4j2Example (Log4j2Example.java:9) - This will be printed on debug
2016-03-11 10:43:52,261 INFO  [main] demo.Log4j2Example (Log4j2Example.java:10) - This will be printed on info
2016-03-11 10:43:52,262 WARN  [main] demo.Log4j2Example (Log4j2Example.java:11) - This will be printed on warn
2016-03-11 10:43:52,262 ERROR [main] demo.Log4j2Example (Log4j2Example.java:12) - This will be printed on error
2016-03-11 10:43:52,262 FATAL [main] demo.Log4j2Example (Log4j2Example.java:13) - This will be printed on fatal
2016-03-11 10:43:52,263 INFO  [main] demo.Log4j2Example (Log4j2Example.java:15) - Appending string: Hello, World.

 

 參考:

http://www.cnblogs.com/yjmyzz/p/3988114.html

http://blog.csdn.net/jiangguilong2000/article/details/11397557

http://memorynotfound.com/log4j2-with-log4j2-xml-configuration-example/

https://logging.apache.org/log4j/2.x/manual/configuration.html

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

當 struts2 加入 struts2-spring-plugin 的 JAR 檔後,執行 JUnit 或 Maven build 時發生 

SEVERE:   [50:59.081] ********** FATAL ERROR STARTING UP STRUTS-SPRING INTEGRATION **********
Looks like the Spring listener was not configured for your web app!
Nothing will work until WebApplicationContextUtils returns a valid ApplicationContext.
You might need to add the following to web.xml:
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
SEVERE:   [50:59.089] Dispatcher initialization failed

 

這時候 JUnit 程式的 extends 要由 StrutsTestCase 變為 StrutsSpringTestCase ,這樣才不會出錯。程式碼如下

package com.mis.example;

import com.opensymphony.xwork2.ActionSupport;

import org.apache.struts2.StrutsSpringTestCase;
import org.apache.struts2.StrutsTestCase;

//public class HelloWorldTest extends StrutsTestCase{
public class HelloWorldTest extends StrutsSpringTestCase {

    public void testHelloWorld() throws Exception {
        HelloWorld hello_world = new HelloWorld();
        String result = hello_world.execute();
        assertTrue("Expected a success result!",
                ActionSupport.SUCCESS.equals(result));
        assertTrue("Expected the default message!",
                hello_world.getText(HelloWorld.MESSAGE).equals(hello_world.getMessage()));
    }
}

 

參考:

http://blog.csdn.net/zj133520/article/details/12620763

http://kang36897.blog.163.com/blog/static/170473732010710101238126/

http://openhome.cc/Gossip/JUnit/

http://linuschien.blogspot.tw/2013/01/unit-test-to-struts2-action-with-spring.html

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

上次介紹 Spring Quartz Job Schedule Simple Example 工作排程器 ,現在再來使用 Spring 原生的 Task Execution and Scheduling,首先來瞭解一下 @Scheduled annotation 的意思

This annotation is used for task scheduling. The trigger information needs to be provided along with this annotation. You can use the properties fixedDelay/fixedRate/cron to provide the triggering information.

1. fixedRate: makes Spring run the task on periodic intervals even if the last invocation may be still running. 固定時間執行,不管上一次是否結束
2. fixedDelay: specifically controls the next execution time when the last execution finishes. 上一次執行結束後,再依設定的固定時間執行
3. cron: is a feature originating from Unix cron utility and has various options based on your requirements. BJ4(就不解釋了)

 

方法 1) Task scheduling using fixed delay attribute in @Scheduled annotation

Step 01: 設定 applicationContext.xml,將 task 選取

applicationContext  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- Spring Task using Annotation-->
    <task:annotation-driven/>
    <bean id="SpringTask-Annotation" class="com.mis.demo.SpringTaskAnnotationDemo"/>
    

</beans>   

 

Step 02: 建立 SpringTaskAnnotationDemo.java

package com.mis.demo;

import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
public class SpringTaskAnnotationDemo {
    @Scheduled(fixedDelay = 5000)
    //@Scheduled(fixedRate = 5000)
    public void demoServiceMethod()
    {
        System.out.println("Method executed at every 5 seconds. Current time is :: "+ new Date());
    }
}

這樣就可以運作了,簡單吧 !!

 

方法 2) Task scheduling using cron expression in @Scheduled annotation

Step 01: 在 applicationContext.xml 設定 class 的 task:scheduled 執行方法,所以在 SpringTaskExecutorDemo.java 的執行 method 為 execute。

    <!-- Spring Task Using cron -->
    <bean id="SpringTask-Cron" class="com.mis.demo.SpringTaskExecutorDemo"/>
    <task:scheduled-tasks>
        <task:scheduled ref="SpringTask-Cron" method="execute" cron="*/5 * * * * ?"/>
    </task:scheduled-tasks>

 

Step 02:  建立 SpringTaskExecutorDemo.java

package com.mis.demo;

import java.util.Calendar;


public class SpringTaskExecutorDemo {
    public void execute () {
        System.out.println("SpringTaskExecutorDemo: Run at " + Calendar.getInstance().getTimeInMillis() );
    }
}

 

這樣就可以運作了,也很簡單吧 !!

 

 

 

 

參考:

http://howtodoinjava.com/spring/spring-core/4-ways-to-schedule-tasks-in-spring-3-scheduled-example/

http://jimwayne.blogspot.tw/2014/04/spring-framework.html

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

MIS 發表在 痞客邦 留言(0) 人氣()

配置:

Maven: pom.xml

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.2</version>
</dependency>

 

Quartz是一個任務進度管理器,以下做簡單的配置

Step 1. 编寫工作(Job class):SpringQuartzJobDemo.java ,需要繼承 spring 中的 QuartzJobBean,因為 QuartzJobBean 類實現了 Job 接口

package com.mis.demo;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

public class SpringQuartzJobDemo extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Business code ..");

    }

}

 

Step 2. Quartz 定時任務,由 Spring 依賴注入配置方法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!-- Spring Quartz -->
    <!--集成方式:MethodInvokingJobDetailFactoryBean,並且任務類別,是需要繼承QuartzJobBean-->
    <!--定義jobDetail-->
    <bean name="schedulingJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.mis.demo.SpringQuartzJobDemo"/>
        <property name="durability" value="true" />        
    </bean>
 
    <!--定義Trigger觸發器: cronExpression 表達式的格式:秒 分 時 日 月 周 年(可選)-->
    <bean id="triggerJob" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="schedulingJob"/>
        <property name="cronExpression" value="*/5 * * * * ?" />
    </bean>
 
        <!--定義核心調度器-->
    <bean id="scheduleController" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="true">
        <property name="schedulerName" value="monitorScheduler"/>
        <property name="triggers">
            <list>            
                 <ref bean="triggerJob"/>
            </list>                
        </property>
    </bean>

    
</beans>

 

Step 3. 完成設定之後,只要啟動Spring並讀取定義檔完成後,排程任務就會進行,

撰寫一個簡單的任務啟動類別:SpringQuartzJobExcute.java

package com.mis.demo;
import org.quartz.SchedulerException;
import org.quartz.impl.StdScheduler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

public class SpringQuartzJobExcute {

    private static ApplicationContext APP_CONTEXT;
    
    public static void main(String[] args) throws SchedulerException {
        APP_CONTEXT = new FileSystemXmlApplicationContext("/src/main/resources/spring-demo-cfg.xml");
        
        System.out.println("Start - ScheduleController");
 
        getScheduleController().start();

    }

    /**
     * get StdScheduler
     *
     * @return StdScheduler
     */
    public static StdScheduler getScheduleController() {
        StdScheduler bean = null;
        bean = (StdScheduler) APP_CONTEXT.getBean("scheduleController", StdScheduler.class);
        return bean;
    }

}

 

 

Cron表達式的格式:秒 分 時 日 月 周 年(可選)。

字段名                 允許的值                        允許的特殊字符

秒                         0-59                               , – * /

分                         0-59                               , – * /

小時                      0-23                               , – * /

日                         1-31                               , – * ? / L W C

月                         1-12 or JAN-DEC            , – * /

周幾                      1-7 or SUN-SAT             , – * ? / L C #

年 (可選字段)     empty, 1970-2099             , – * /

 “?”字符:表示不確定的值

 “,”字符:指定數個值

“-”字符:指定一個值的範圍

“/”字符:指定一個值的增加幅度。n/m表示從n開始,每次增加m

“L”字符:用在日表示一個月中的最後一天,用在周表示該月最後一個星期X

“W”字符:指定離给定日期最近的工作日(周一到周五)

“#”字符:表示該月第幾個周X。6#3表示該月第3個周五

 

Cron表達式範例:

每隔5秒執行一次:*/5 * * * * ?

每隔1分鐘執行一次:0 */1 * * * ?

每天23點執行一次:0 0 23 * * ?

每天淩晨1點執行一次:0 0 1 * * ?

每月1號淩晨1點執行一次:0 0 1 1 * ?

每月最後一天23點執行一次:0 0 23 L * ?

每周星期天淩晨1點實行一次:0 0 1 ? * L

在26分、29分、33分執行一次:0 26,29,33 * * * ?

每天的0點、13點、18點、21點都執行一次:0 0 0,13,18,21 * * ?

 

參考資料: http://quartz-scheduler.org/documentation

 

參考:

http://wp.mlab.tw/?p=1701

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

http://quartz-scheduler.org/overview/quick-start

 

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

看完 Spring Data JPA 基本篇 與 Spring Data JPA 進階篇 之後,再來看一下 Spring Data JPA 框架,它主要針對的就是 Spring 唯一沒有簡化到的業務邏輯代碼。接下來我們針對前面的例子進行改造,讓 Spring Data JPA 來幫助我們完成業務邏輯。在著手寫代碼之前,開發者需要先 下載Spring Data JPA 的發佈包(需要同時下載 Spring Data Commons 和 Spring Data JPA 兩個發佈包,Commons 是 Spring Data 的公共基礎包),並把相關的依賴 JAR 檔加入到 CLASSPATH 中。

 

Step 01: DAO Interface: PersonSpringDataJPADao.java

package com.mis.demos.dao;

import org.springframework.data.repository.Repository;

import com.mis.demos.model.Person;
public interface PersonSpringDataJPADao extends Repository<Person, Integer> {

    public Person save(Person person);
    
}

expends Repository 時,需要宣告 public Person save(Person person); 作為儲存的方法。expends CrudRepository 或 JpaRepository 時,則不需宣告,如下:

package com.mis.demos.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.mis.demos.model.Person;
@Repository("PersonSpringDataJPADao")
public interface PersonSpringDataJPADao extends JpaRepository<Person, Integer> {

    
}

不要懷疑,就只是宣告一個 Interface 而已,而且是空的;至於加入 @Repository("PersonSpringDataJPADao") 只是讓 Control 層也能直接引用。

Step 02: Service: PersonSpringDataJPAService.java

package com.mis.demos.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mis.demos.dao.PersonSpringDataJPADao;
import com.mis.demos.model.Person;

@Service("PersonSpringDataJPAService")
public class PersonSpringDataJPAService {

    @Autowired
    PersonSpringDataJPADao personSpringDataJPADao;
    
    public Person saveAccount(Person person){
        return personSpringDataJPADao.save(person);
    }
    public Person findPersonById(Integer id){
        return personSpringDataJPADao.findOne(id);
    }
}

 

Step 03:  spring-demo-cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!-- 聲明Spring要管理的範圍
    只要搜尋 service 一個 package 就可以了,model 交給 EntityManager 負責,dao 交給 Spring Data JPA 負責。-->
    <context:component-scan base-package="com.mis" />    

    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <bean id="entityManagerFactory"    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">        
    </bean>

    <!--  Spring Data JPA 的設定 -->
    <jpa:repositories base-package="com.mis.demos.dao"/>
    
</beans>

 

Step 04: 新增測試

package com.mis.demos;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mis.demos.dao.PersonDao;
import com.mis.demos.dao.PersonSpringDataDao;
import com.mis.demos.dao.PersonSpringDataJPADao;
import com.mis.demos.model.Person;
import com.mis.demos.services.PersonPU;
import com.mis.demos.services.PersonService;
import com.mis.demos.services.PersonSpringDataJPAService;
import com.mis.demos.services.PersonSpringDataService;
import com.mis.demos.services.PersonSpringDataServiceImpl;
public class SimpleSpringJpaDemo {

    public static void main(String[] args) {

        doSpringDataJPASave();
        
    }
   
    public static void doSpringDataJPASave(){
        Person person = new Person();
        Person who = new Person();
        List<Person> allPerson= new ArrayList<Person>();

        //person.setId(1);
        person.setFirstName("polin-99-3");
        person.setLastName("wei-99-2");
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-demo-cfg.xml");
        // 透過 Service
        PersonSpringDataJPAService personSpringDataJPAService = ctx.getBean("PersonSpringDataJPAService",PersonSpringDataJPAService.class);
        personSpringDataJPAService.saveAccount(person);
        who = personSpringDataJPAService.findPersonById(person.getId());
        System.out.println(who.getFirstName());
        //直接呼叫 DAO
        PersonSpringDataJPADao personSpringDataJPADao = ctx.getBean("PersonSpringDataJPADao",PersonSpringDataJPADao.class);
        //personSpringDataJPADao.delete(who.getId());
        allPerson = personSpringDataJPADao.findAll();
        for (Person person2 : allPerson) {
            System.out.println(person2.getId());
        }
        ctx.close();
    }

}

 

真的可以寫入耶,真是太棒了.

 

Step 05: 在 DAO: PersonSpringDataJPADao.java,使用 @Query 提供自訂查詢語句示例

package com.mis.demos.dao;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import com.mis.demos.model.Person;
@Repository("PersonSpringDataJPADao")
public interface PersonSpringDataJPADao extends JpaRepository<Person, Integer> {

    //使用 @Query 提供自訂查詢語句示例
    @Query("select p from Person p where p.firstName = ?1")
    public List<Person> findByFirstName(String FirstName);
}

 

Step 06: 查詢測試

package com.mis.demos;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mis.demos.dao.PersonDao;
import com.mis.demos.dao.PersonSpringDataDao;
import com.mis.demos.dao.PersonSpringDataJPADao;
import com.mis.demos.model.Person;
import com.mis.demos.services.PersonPU;
import com.mis.demos.services.PersonService;
import com.mis.demos.services.PersonSpringDataJPAService;
import com.mis.demos.services.PersonSpringDataService;
import com.mis.demos.services.PersonSpringDataServiceImpl;
public class SimpleSpringJpaDemo {

    public static void main(String[] args) { 

        doSpringDataJPASave();
        
    }

    
    public static void doSpringDataJPASave(){
        Person person = new Person();
        Person who = new Person();
        List<Person> allPerson= new ArrayList<Person>();

        //person.setId(1);
        person.setFirstName("polin-99-3");
        person.setLastName("wei-99-2");
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-demo-cfg.xml");
        PersonSpringDataJPAService personSpringDataJPAService = ctx.getBean("PersonSpringDataJPAService",PersonSpringDataJPAService.class);
        personSpringDataJPAService.saveAccount(person);
        who = personSpringDataJPAService.findPersonById(person.getId());
        System.out.println(who.getFirstName());
        PersonSpringDataJPADao personSpringDataJPADao = ctx.getBean("PersonSpringDataJPADao",PersonSpringDataJPADao.class);
        //personSpringDataJPADao.delete(who.getId());
        allPerson = personSpringDataJPADao.findAll();
        for (Person person2 : allPerson) {
            System.out.println(person2.getId());
        }
        allPerson = personSpringDataJPADao.findByFirstName("polin-99-3");
        for (Person person2 : allPerson) {
            System.out.println(person2.getId());
        }
        ctx.close();
    }

}

 

 本文主要介紹了 Spring Data JPA 的使用,以及它與 Spring 框架的無縫集成。Spring Data JPA 其實並不依賴於 Spring 框架。

參考:

http://spring.io/blog/2011/02/10/getting-started-with-spring-data-jpa/

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

Spring Data JPA 基本篇 談到 JPA 的基本作業,現在加入 Spring 的注入(Dependency Injection)來看,Spring 簡化程式碼有多少.

Step 01: DAO Interface: PersonSpringDataDao.java

package com.mis.demos.dao;

import com.mis.demos.model.Person;

public interface PersonSpringDataDao {

    public Person Save(Person person);
    
}

 

Step 02: DAO Implement: PersonSpringDataDaoImpl.java

package com.mis.demos.dao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.mis.demos.model.Person;
@Repository("PersonSpringDataDao")
public class PersonSpringDataDaoImpl implements PersonSpringDataDao {

     @PersistenceContext
     private EntityManager em;
    
    @Transactional
    public Person Save(Person person) {
        if (person.getId()==null)
            em.persist(person);
        else
            em.merge(person);
        return person;
    }

}

 

Step 03: Service Interface: PersonSpringDataService.java

package com.mis.demos.services;

import com.mis.demos.model.Person;

public interface PersonSpringDataService {

    public Person saveAccount(Person person);
}

 

Step 04: Service implement: PersonSpringDataServiceImpl.java , Spring 完成依賴注入,因此不再需要使用 new 操作符創建 PersonSpringDataDaoImpl 物件了

package com.mis.demos.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mis.demos.dao.PersonSpringDataDao;
import com.mis.demos.dao.PersonSpringDataDaoImpl;
import com.mis.demos.model.Person;

@Service("PersonSpringDataService")
public class PersonSpringDataServiceImpl implements PersonSpringDataService {

    //private PersonSpringDataDao personSpringDataDao = new PersonSpringDataDaoImpl();
    @Autowired
    private PersonSpringDataDao personSpringDataDao;
    @Transactional
    public Person saveAccount(Person person) {
        
        return personSpringDataDao.Save(person);
    }

}

 

Step 05:  建立 Spring 設定檔: spring-demo-cfg.xml ,它會去參考 META-INF\persistence.xml 裡的 persistence-unit ,只有一個 PU 時, 則為預設的 data source

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!-- 聲明Spring要管理的範圍 -->
    <context:component-scan base-package="com.mis" />       

    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <bean id="entityManagerFactory"    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">        
    </bean>

</beans>

 

Step 06: 測試

package com.mis.demos;

import javax.annotation.Resource;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mis.demos.dao.PersonDao;
import com.mis.demos.dao.PersonSpringDataDao;
import com.mis.demos.model.Person;
import com.mis.demos.services.PersonPU;
import com.mis.demos.services.PersonService;
import com.mis.demos.services.PersonSpringDataService;
import com.mis.demos.services.PersonSpringDataServiceImpl;
public class SimpleSpringJpaDemo {

    public static void main(String[] args) {        

        doSpringDataJPASave();
    }
   
   
    public static void doSpringDataJPASave(){
        Person person = new Person();

        person.setId(1);
        person.setFirstName("polin-9-12");
        person.setLastName("wei-9-12");
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-demo-cfg.xml");
        //PersonSpringDataDao personSpringDataDao = ctx.getBean("PersonSpringDataDao",PersonSpringDataDao.class);
        //personSpringDataDao.Save(person);
        // 注意這裡是取得 Service Interface : PersonSpringDataService.java , 不是實作 PersonSpringDataServiceImpl.java
        PersonSpringDataService personSpringDataService = ctx.getBean("PersonSpringDataService",PersonSpringDataService.class);
        personSpringDataService.saveAccount(person);
        ctx.close();
        
    }

}

 

由此可知,通過與 Spring Data JPA 基本篇 程式碼的對比,程式重構前後的代碼,可以發現 Spring 對 JPA 的簡化已經非常出色了,可以大致總結一下 Spring 框架對 JPA 提供的支援主要體現在如下幾個方面:


•    首先,它使得 JPA 配置變得更加靈活。JPA 規範要求,設定檔必須命名為 persistence.xml,並存在於類路徑下的 META-INF 目錄中。該檔通常包含了初始化 JPA 引擎所需的全部資訊。Spring 提供的 LocalContainerEntityManagerFactoryBean 提供了非常靈活的配置,persistence.xml 中的資訊都可以在此以屬性注入的方式提供。

•    其次,Spring 實現了部分在 EJB 容器環境下才具有的功能,比如對 @PersistenceContext、@PersistenceUnit 的容器注入支援。

•    第三,也是最具意義的,Spring 將 EntityManager 的創建與銷毀、事務管理等代碼抽取出來,並由其統一管理,開發者不需要關心這些,如前面的代碼所示,業務方法中只剩下操作領域物件的代碼,事務管理和 EntityManager 創建、銷毀的代碼都不再需要開發者關心了。

 

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

本文的示例代碼基於 Hibernate EntityManager 開發,程式碼中使用到的都是 JPA 規範提供的Interface / Class,以便瞭解 JPA 基本的概念。整個系統架構如下

jpa-mis  

Step 01 : create mysql table: person

CREATE TABLE `person` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `firstName` varchar(45) NOT NULL,
  `lastName` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

 

 Step 02: 利用 Hibernate Tool 自動建立 Entity model :Person.java

package com.mis.demos.model;
// Generated Jan 20, 2016 10:35:00 AM by Hibernate Tools 4.3.1

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 * Person generated by hbm2java
 */
@Entity
@Table(name = "person", catalog = "spring")
public class Person implements java.io.Serializable {

    private Integer id;
    private String firstName;
    private String lastName;

    public Person() {
    }

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)

    @Column(name = "id", unique = true, nullable = false)
    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(name = "firstName", nullable = false, length = 45)
    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @Column(name = "lastName", nullable = false, length = 45)
    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

}

 

Step 03: 直接用 Service 去存取 table ,不建立 DAO (Data Access Object),正常來說,是應該要先建立 DAO 的,我有點偷懶...:

package com.mis.demos.services;


import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import com.mis.demos.model.Person;
/**
 * 沒有透過 DAO 操作 CRUD
 * @author polin.wei
 *
 */
public class PersonPU {

    private EntityManager em;
    private EntityManagerFactory emf;
    
    
    public void clientSave(Person person){        
        emf = Persistence.createEntityManagerFactory("mysqlLocalPU");
        em = emf.createEntityManager();        
        if (person.getId()==null){
            // new
            em.getTransaction().begin();
            em.persist(person);
            em.getTransaction().commit();
        } else {
            // update
            em.getTransaction().begin();
            em.merge(person);
            em.getTransaction().commit();
        }
        em.close();
        emf.close();
    }
}

 

Step 04: 建立 src\main\resources\META-INF\persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    version="2.0">
    <persistence-unit name="mysqlLocalPU"
        transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <property name="hibernate.connection.driver_class" value="org.gjt.mm.mysql.Driver" />
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/spring" />
            <property name="hibernate.connection.username" value="root" />
            <property name="hibernate.connection.password" value="root" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.use_sql_comments" value="false" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
        </properties>
    </persistence-unit>

</persistence>

 

Step 05: 測試

package com.mis.demos;

import javax.annotation.Resource;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mis.demos.dao.PersonDao;
import com.mis.demos.dao.PersonSpringDataDao;
import com.mis.demos.model.Person;
import com.mis.demos.services.PersonPU;
import com.mis.demos.services.PersonService;
import com.mis.demos.services.PersonSpringDataService;
import com.mis.demos.services.PersonSpringDataServiceImpl;
public class SimpleSpringJpaDemo {

    public static void main(String[] args) {
        
        doPersistenceSave();

    }

    public static void doPersistenceSave(){
        Person person = new Person();
        // 利用 ID 是否有給值來作 save & update 的判斷
        person.setId(2);
        person.setFirstName("polin-2-6");
        person.setLastName("wei-2-6");

        new PersonPU().clientSave(person);        
    }
 

}

 

 

從 Spring + Hibernate 到 Spring Data JPA

http://cw1057.blogspot.tw/2013/12/more-in-spring-data-jpa-150-m1.html

https://struts.apache.org/docs/struts-2-spring-2-jpa-ajax.html#Struts2+Spring2+JPA+AJAX-Themavenway

https://www.ibm.com/developerworks/cn/opensource/os-cn-spring-jpa/

http://www.mastertheboss.com/jboss-frameworks/hibernate-jpa/jpa-configuration/how-to-use-multiple-database-in-persistencexml

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()