2,从零开始搭建SSHM开发框架(集成Spring+JPA)

目录

本专题博客已共享在

https://code.csdn.net/yangwei19680827/maven_sshm_blog

1,从零开始搭建SSHM开发框架(环境准备)

2,从零开始搭建SSHM开发框架(集成Spring+JPA)

(还在写…)3,从零开始搭建SSHM开发框架(集成Spring MVC)

(还在写…)4,从零开始搭建SSHM开发框架(集成DWZ+Spring Security)

(还在写呢。。。)5,从零开始搭建SSHM开发框架(DWZ的使用)

(还在写呢。。。)6,从零开始搭建SSHM开发框架(集成Ehcache)

(还在写呢。。。)7,从零开始搭建SSHM开发框架(集成activemq)

(还在写呢。。。)8,从零开始搭建SSHM开发框架(集成Mybatis)

(还在写呢。。。)9,从零开始搭建SSHM开发框架(集成Redis)

1.修改pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.wiker</groupId>
    <artifactId>sshm</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>sshm Maven Webapp</name>
    <url>http://maven.apache.org</url>
    
    <properties>
        <hibernate-version>5.1.0.Final</hibernate-version>
        <spring-version>4.2.5.RELEASE</spring-version>
        <log4j-version>1.2.17</log4j-version>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jdk.version>1.8</jdk.version>
    </properties>
    <dependencies>

        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate-version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate-version}</version>
        </dependency>
        
        <!-- mysql 驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>

        <!-- Spring,JPA start -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <!-- 阿里的数据源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.22</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j-version}</version>
        </dependency>
        
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>sshm</finalName>
    </build>
</project>

2.增加applicationContext-service.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:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:task="http://www.springframework.org/schema/task"
       xmlns:cache="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/jdbc
        http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
        http://www.springframework.org/schema/jee
        http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache-3.2.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
        http://www.directwebremoting.org/schema/spring-dwr
        http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd
        http://www.springframework.org/schema/task
        http://www.springframework.org/schema/task/spring-task-3.1.xsd"
        default-lazy-init="true">

    <description>Spring Service Configration</description>

    <!--<context:annotation-config/>-->
    <!-- scan service class with @components ;这里的扫描包名可以按需修改 -->
    <context:component-scan base-package="com.wiker" />
    
    <context:annotation-config/>


    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:application.properties</value>
            </list>
        </property>
    </bean>
    
    
    <!-- 整合mysqljpa -->
    <bean id="mysqlEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="mysqlDataSource"></property>
        <property name="packagesToScan" value="com.wiker"></property>
        <property name="persistenceUnitName" value="mysqldb"></property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--<property name="showSql" value="true"></property>-->
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <!--设置外连接抓取树的最大深度 -->
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.jdbc.fetch_size">18</prop>
                <prop key="hibernate.jdbc.batch_size">10</prop>
                <!-- 命名规则 My_NAME->MyName -->
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.DefaultNamingStrategy</prop>
                <prop key="hibernate.hbm2ddl.auto">${generateDdl}</prop>
                <!-- 自动建表类型 validate|create|create-drop|update -->
                <!-- <prop key="hibernate.hbm2ddl.auto">validate</prop> -->
                <!-- 是否显示SQL -->
                <prop key="hibernate.show_sql">${showSql}</prop>
                <!-- 显示SQL是否格式化 -->
                <prop key="hibernate.format_sql">${format_sql}</prop>
                <!-- 关闭二级缓存 -->
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
                <!-- 关闭实体字段映射校验 -->
                <prop key="javax.persistence.validation.mode">none</prop>
            </props>
        </property>
    </bean>

    <!-- Jpa 事务配置 -->
    <bean id="mysqltransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="mysqlEntityManagerFactory" />
    </bean>
    
    <!-- 使用annotation定义事务 -->
    <tx:annotation-driven transaction-manager="mysqltransactionManager"
                          proxy-target-class="true" />

    <!-- Spring Data Jpa配置 repository扫描的包名-->
    <jpa:repositories base-package="com.wiker"
                      transaction-manager-ref="mysqltransactionManager"
                      entity-manager-factory-ref="mysqlEntityManagerFactory" />


    <beans profile="production">
        <context:property-placeholder
                ignore-resource-not-found="true"
                location="classpath*:/application.properties" />
        <!-- mysql数据源配置 -->
        <bean id="mysqlDataSource" class="com.alibaba.druid.pool.DruidDataSource"
              init-method="init" destroy-method="close">
            <!-- 驱动名称 -->
            <property name="DriverClassName" value="${jdbc.driver}" />
            <!-- JDBC连接串 -->
            <property name="url" value="${jdbc.url}" />
            <!-- 数据库用户名称 -->
            <property name="username" value="${jdbc.username}" />
            <!-- 数据库密码 -->
            <property name="password" value="${jdbc.password}" />
            <!-- 连接池最大使用连接数量 -->
            <property name="maxActive" value="${jdbc.maxActive}" />
            <!-- 初始化大小 -->
            <property name="initialSize" value="${jdbc.initialSize}" />
            <!-- 获取连接最大等待时间 -->
            <property name="maxWait" value="${jdbc.maxWait}" />
            <!-- 连接池最小空闲 -->
            <property name="minIdle" value="${jdbc.minIdle}" />
            <!-- 逐出连接的检测时间间隔 -->
            <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" />
            <!-- 最小逐出时间 -->
            <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" />
            <!-- 测试有效用的SQL Query -->
            <property name="validationQuery" value="SELECT 'x'" />
            <!-- 连接空闲时测试是否有效 -->
            <property name="testWhileIdle" value="true" />
            <!-- 获取连接时测试是否有效 -->
            <property name="testOnBorrow" value="false" />
            <!-- 归还连接时是否测试有效 -->
            <property name="testOnReturn" value="false" />
        </bean>
    </beans>

</beans>

3.增加application.properties配置文件

#mysql database setting
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=root
jdbc.maxActive=2000
jdbc.initialSize=50
jdbc.maxWait=60000
jdbc.minIdle=50
jdbc.timeBetweenEvictionRunsMillis=3000
jdbc.minEvictableIdleTimeMillis=300000
showSql=true
format_sql = true
#validate               加载hibernate时,验证创建数据库表结构
#create                  每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。
#create-drop        加载hibernate时创建,退出是删除表结构
#update                 加载hibernate自动更新数据库结构
#none   不更新表结构
generateDdl=update


4.增加log4j.properties配置

###############################log4j.properties###############################
##### Global Log Level(OFF,FATAL,ERROR,WARN,INFO,DEBUG,ALL) #############
#log4j.rootLogger=info,stdout,info,debug,error
log4j.rootLogger=ALL,STDOUT,FILELOGER

###### STDOUT Logger ###############
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.Threshold=DEBUG
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=[%d{yyy-MM-dd HH:mm:ss.SSS}] [%p] - [%m]%n



5.修改web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>

    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>messages</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:/applicationContext-service.xml
        </param-value>
    </context-param>
    <context-param>
        <param-name>spring.profiles.default</param-name>
        <param-value>production</param-value>
    </context-param>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
  <display-name>Archetype Created Web Application</display-name>
</web-app>


6.增加实体、DAO

TestEntity.java

package com.wiker.entity;

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

@Entity
@Table(name = "t_test",catalog = "test")
public class TestEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Long id;
    
    @Column(name="content")
    private String content;

    public Long getId() {
        return id;
    }

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

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
    
    
}


TestDao.java

package com.wiker.repository;

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.PagingAndSortingRepository;

import com.wiker.entity.TestEntity;

public interface TestDao extends PagingAndSortingRepository<TestEntity, Long>, 
    JpaSpecificationExecutor<TestEntity> {

}


TestService.java

package com.wiker.service;

import java.util.List;

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

import com.wiker.entity.TestEntity;
import com.wiker.repository.TestDao;

@Service
@Transactional(readOnly = true)
public class TestService {

    @Autowired
    private TestDao testDao;
    
    @Transactional(readOnly=false)
    public TestEntity add(TestEntity t){
        return testDao.save(t);
    }
    
    public List<TestEntity> getAll(){
        return (List<TestEntity>) testDao.findAll();
    }
}

7.增加java测试类,新建的类放到src/test/java中

BaseProductionProfiles.java

package com.wiker.test;

import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * Created by wiker on 2016/3/21.
 */
@RunWith(SpringJUnit4ClassRunner.class)
//@PropertySource(name = AbstractEnvironment.DEFAULT_PROFILES_PROPERTY_NAME,value = "test")
@ActiveProfiles("production")
@ContextConfiguration(locations = { "classpath:applicationContext-service.xml"})
public class BaseProductionProfiles extends AbstractTransactionalJUnit4SpringContextTests {



    @Test
    @Ignore
    public void test(){}
}

JunitTestService.java

package com.wiker.test;
import java.util.List;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.wiker.entity.TestEntity;
import com.wiker.service.TestService;

/**
 * Created by wiker on 2016-06-22.
 */
public class JunitTestService extends BaseProductionProfiles {

    @Autowired
    private TestService testService;

    @Test
    public void testDao(){
        TestEntity test = new TestEntity();
        test.setContent("测试的内容");
        //插入数据
        testService.add(test);
        
        //查询数据
        List<TestEntity> list = (List<TestEntity>) testService.getAll();
        for(TestEntity t:list){
            System.out.println("Content:"+t.getContent());
        }
        
    }
}


8.Junit运行JunitTestService

可以去test数据库看,表应该生成了。测试的内容也打印了(细心的同学会发现,通过测试的数据貌似是不会真正的写到数据库,如果需要真正的写数据库可以在BaseProductionProfiles.java中使用@TransactionConfiguration注解)。如下图:

最后的项目结构

9.JPA一些其它的用法

  • And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
  • Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
  • Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int ma- x, int min);
  • LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
  • GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
  • IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
  • IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
  • NotNull --- 与 IsNotNull 等价;
  • Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
  • NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
  • OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
  • Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
  • In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
  • NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

** 如果上面的也不能满足?没关系JPA也提供了使用JPQL的语句,比较类似HQL **

  • 使用 @Query 提供自定义查询语句示例
 public interface UserDao extends Repository<AccountInfo, Long> { 

     @Query("select a from AccountInfo a where a.accountId = ?1") 
     public AccountInfo findByAccountId(Long accountId); 

    @Query("select a from AccountInfo a where a.balance > ?1") 
     public Page<AccountInfo> findByBalanceGreaterThan( 
 Integer balance,Pageable pageable); 
 }

** 如果有update的呢,也没关系,使用@Modifying注解 **

@Modifying 
@Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2") 
public int increaseSalary(int after, int before);

10.想分页查询怎么办?JPA也有强大的支持

可以看看我们写的DAO中有哪些方法:

JPA分页

看见findAll(Pageable arg0)这个方法没,通过传一个Pageable的参数就可以了。可以看到dao里面还有其它常用的方法,如排序。
还有findAll(Specification<T> spec, Pageable pageable); Specification是什么,这里面可以封装一些查询条件。这里可以推荐一个开源的框架,springside。或者自己写也不难,如下图:

条件查询

看看我写的service,如图:


条件查询

这个service就可以支持一个表的全部条件查询,我就只需要修改我的页面了,加一个条件查询我只需要修改JSP(这里表示根据dictName字段去like查询),爽吧,这样单表的CRUD基本上可以很简单的写个工具生成代码了(后面也给整理出来)。比如:

<td>字典名称:<input type="text" name="search_LIKE_dictName" value="${param.search_LIKE_dictName}" /></td>
<td>显示名:<input type="text" name="search_LIKE_dictKey" value="${param.search_LIKE_dictKey}" /></td>

TIPS

  • 有可能目录结构中没有src/main/java的目录,如果没有新建一个便可

本章程序源码下载地址

http://download.csdn.net/detail/yangwei19680827/9592869

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容