目前分類:Struts2 + Spring4 + Hibernate4 (10)

瀏覽方式: 標題列表 簡短摘要

用 Hibernet Tool 自動產生的 Domain Code,對於 FOREIGN KEY 會以 annotation:  @ManyToMany(fetch = FetchType.LAZY) 來作註,但執行時會發生下列的錯誤

Struts Problem Report

Struts has detected an unhandled exception:

Messages:
  • failed to lazily initialize a collection of role: com.mis.model.Admin.roles, could not initialize proxy - no Session
File: org/hibernate/collection/internal/AbstractPersistentCollection.java
 

Stacktraces

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mis.model.Admin.roles, could not initialize proxy - no Session

 

解決方法: 由 FetchType.LAZY 改成 FetchType.EAGER

    //@ManyToMany(fetch = FetchType.LAZY)
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "admin_roles", catalog = "weixin", joinColumns = {
            @JoinColumn(name = "aid", nullable = false, updatable = false) }, inverseJoinColumns = {
                    @JoinColumn(name = "rid", nullable = false, updatable = false) })
    public Set<Role> getRoles() {
        return this.roles;
    }

 

或者是在 applicationContext.xml 加入 <prop key="hibernate.enable_lazy_load_no_trans">true</prop> 如下

    <!-- Configure the entity manager factory bean : Step02-Start-->    
    <bean id="emfLocalDS"    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">        
        <property name="dataSource" ref="LocalDS"></property>         
        <property name="persistenceUnitName" value="emfLocalPU"/>
        <!-- Set base package of your entities -->
        <property name="packagesToScan" value="com.mis.model"/>
        <!-- Set share cache mode -->
        <property name="sharedCacheMode" value="ENABLE_SELECTIVE"/>
        <!-- Set validation mode -->
        <property name="validationMode" value="NONE"/>         
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="MYSQL" />
                <property name="showSql" value="true" />
            </bean>
        </property>

        <!-- Set JPA properties -->
        <property name="jpaProperties">
            <props>
                 <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                 <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
            </props>
        </property>       
    </bean>
    <!-- Configure the entity manager factory bean : Step02-End-->

參考:

http://stackoverflow.com/questions/11746499/solve-failed-to-lazily-initialize-a-collection-of-role-exception

http://www.lostinsoftware.com/2015/08/reverse-engineering-and-code-generation/

文章標籤

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

作法如下:

http://stackoverflow.com/questions/26616723/java-lang-nosuchmethoderror-javax-persistence-table-indexesljavax-persistenc

If you are using Jboss 7.1.1, jboss already has hibernate-jpa-2.0 in its classpath, so during runtime it uses the one in its classpath, not the one you've deployed with your app , to point jboss to the hibernate-jpa-2.1 do the following:

  1. copy hibernate-jpa-2.1-api-1.0.0.final.jar to the following directory : jboss-as-7.1.1.Final/modules/javax/persistence/api/main

  2. open module.xml and change the resource-root as follows : resource-root path="hibernate-jpa-2.1-api-1.0.0.final.jar" (pointing it to jpa 2.1)

  3. re-compile and re-deploy your app, then you are good to go.

module.xml 檔案內容, 置換成 hibernate-jpa-2.1-api-1.0.0.Final.jar :

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

<!--
  ~ JBoss, Home of Professional Open Source.
  ~ Copyright 2010, Red Hat, Inc., and individual contributors
  ~ as indicated by the @author tags. See the copyright.txt file in the
  ~ distribution for a full listing of individual contributors.
  ~
  ~ This is free software; you can redistribute it and/or modify it
  ~ under the terms of the GNU Lesser General Public License as
  ~ published by the Free Software Foundation; either version 2.1 of
  ~ the License, or (at your option) any later version.
  ~
  ~ This software is distributed in the hope that it will be useful,
  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  ~ Lesser General Public License for more details.
  ~
  ~ You should have received a copy of the GNU Lesser General Public
  ~ License along with this software; if not, write to the Free
  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  -->

<module xmlns="urn:jboss:module:1.1" name="javax.persistence.api">
    <dependencies>
        <!-- PersistenceUnitInfo needs javax.sql.DataSource -->
        <module name="javax.api" export="true"/>
    </dependencies>

    <resources>
        <resource-root path="hibernate-jpa-2.1-api-1.0.0.Final.jar"/>
        <!-- Insert resources here -->
    </resources>
</module>

 

文章標籤

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

在目錄 %JBOSS_HOME%\modules\com\microsoft\sqlserver\jdbc\main 下放入 module.xml & sqljdbc42.jar

module.xml 的內容

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.microsoft.sqlserver.jdbc">
 <resources>
  <resource-root path="sqljdbc42.jar"/>
 </resources>
 <dependencies>
  <module name="javax.api"/>
  <module name="javax.xml.bind.api"/>
  <module name="javax.transaction.api"/>
 </dependencies>
</module>

編輯 %JBOSS_HOME%\standalone\configuration\standalone.xml

<datasource jndi-name="java:/mssqlDS" pool-name="LansweeperDS" enabled="true">
    <connection-url>jdbc:sqlserver://mssql_IP\SQLEXPRESS;DatabaseName=mydb</connection-url>
    <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>
    <driver>sqlserver</driver>
    <security>
        <user-name>sa</user-name>
        <password>password</password>
    </security>
    <validation>
        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLValidConnectionChecker"/>
    </validation>
</datasource>

<driver name="sqlserver" module="com.microsoft.sqlserver.jdbc">
    <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerXADataSource</xa-datasource-class>
</driver>

這樣就可以了

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

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) 人氣()

當 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) 人氣()

配置:

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) 人氣()