目錄
本專題博客已共享在
https://code.csdn.net/yangwei19680827/maven_sshm_blog
1,從零開始搭建SSHM開發(fā)框架(環(huán)境準(zhǔn)備)
2,從零開始搭建SSHM開發(fā)框架(集成Spring+JPA)
(還在寫…)3,從零開始搭建SSHM開發(fā)框架(集成Spring MVC)
(還在寫…)4,從零開始搭建SSHM開發(fā)框架(集成DWZ+Spring Security)
(還在寫呢。。。)5,從零開始搭建SSHM開發(fā)框架(DWZ的使用)
(還在寫呢。。。)6,從零開始搭建SSHM開發(fā)框架(集成Ehcache)
(還在寫呢。。。)7,從零開始搭建SSHM開發(fā)框架(集成activemq)
(還在寫呢。。。)8,從零開始搭建SSHM開發(fā)框架(集成Mybatis)
(還在寫呢。。。)9,從零開始搭建SSHM開發(fā)框架(集成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 驅(qū)動(dòng) -->
<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>
<!-- 阿里的數(shù)據(jù)源 -->
<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>
<!--設(shè)置外連接抓取樹的最大深度 -->
<prop key="hibernate.max_fetch_depth">3</prop>
<prop key="hibernate.jdbc.fetch_size">18</prop>
<prop key="hibernate.jdbc.batch_size">10</prop>
<!-- 命名規(guī)則 My_NAME->MyName -->
<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.DefaultNamingStrategy</prop>
<prop key="hibernate.hbm2ddl.auto">${generateDdl}</prop>
<!-- 自動(dòng)建表類型 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>
<!-- 關(guān)閉二級(jí)緩存 -->
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<!-- 關(guān)閉實(shí)體字段映射校驗(yàn) -->
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
</bean>
<!-- Jpa 事務(wù)配置 -->
<bean id="mysqltransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="mysqlEntityManagerFactory" />
</bean>
<!-- 使用annotation定義事務(wù) -->
<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數(shù)據(jù)源配置 -->
<bean id="mysqlDataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!-- 驅(qū)動(dòng)名稱 -->
<property name="DriverClassName" value="${jdbc.driver}" />
<!-- JDBC連接串 -->
<property name="url" value="${jdbc.url}" />
<!-- 數(shù)據(jù)庫(kù)用戶名稱 -->
<property name="username" value="${jdbc.username}" />
<!-- 數(shù)據(jù)庫(kù)密碼 -->
<property name="password" value="${jdbc.password}" />
<!-- 連接池最大使用連接數(shù)量 -->
<property name="maxActive" value="${jdbc.maxActive}" />
<!-- 初始化大小 -->
<property name="initialSize" value="${jdbc.initialSize}" />
<!-- 獲取連接最大等待時(shí)間 -->
<property name="maxWait" value="${jdbc.maxWait}" />
<!-- 連接池最小空閑 -->
<property name="minIdle" value="${jdbc.minIdle}" />
<!-- 逐出連接的檢測(cè)時(shí)間間隔 -->
<property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" />
<!-- 最小逐出時(shí)間 -->
<property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" />
<!-- 測(cè)試有效用的SQL Query -->
<property name="validationQuery" value="SELECT 'x'" />
<!-- 連接空閑時(shí)測(cè)試是否有效 -->
<property name="testWhileIdle" value="true" />
<!-- 獲取連接時(shí)測(cè)試是否有效 -->
<property name="testOnBorrow" value="false" />
<!-- 歸還連接時(shí)是否測(cè)試有效 -->
<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時(shí),驗(yàn)證創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu)
#create 每次加載hibernate,重新創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu),這就是導(dǎo)致數(shù)據(jù)庫(kù)表數(shù)據(jù)丟失的原因。
#create-drop 加載hibernate時(shí)創(chuàng)建,退出是刪除表結(jié)構(gòu)
#update 加載hibernate自動(dòng)更新數(shù)據(jù)庫(kù)結(jié)構(gòu)
#none 不更新表結(jié)構(gòu)
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.增加實(shí)體、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測(cè)試類,新建的類放到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("測(cè)試的內(nèi)容");
//插入數(shù)據(jù)
testService.add(test);
//查詢數(shù)據(jù)
List<TestEntity> list = (List<TestEntity>) testService.getAll();
for(TestEntity t:list){
System.out.println("Content:"+t.getContent());
}
}
}
8.Junit運(yùn)行JunitTestService
可以去test數(shù)據(jù)庫(kù)看,表應(yīng)該生成了。測(cè)試的內(nèi)容也打印了(細(xì)心的同學(xué)會(huì)發(fā)現(xiàn),通過測(cè)試的數(shù)據(jù)貌似是不會(huì)真正的寫到數(shù)據(jù)庫(kù),如果需要真正的寫數(shù)據(jù)庫(kù)可以在BaseProductionProfiles.java中使用@TransactionConfiguration注解)。如下圖:
最后的項(xiàng)目結(jié)構(gòu)
9.JPA一些其它的用法
- And --- 等價(jià)于 SQL 中的 and 關(guān)鍵字,比如 findByUsernameAndPassword(String user, Striang pwd);
- Or --- 等價(jià)于 SQL 中的 or 關(guān)鍵字,比如 findByUsernameOrAddress(String user, String addr);
- Between --- 等價(jià)于 SQL 中的 between 關(guān)鍵字,比如 findBySalaryBetween(int ma- x, int min);
- LessThan --- 等價(jià)于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
- GreaterThan --- 等價(jià)于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
- IsNull --- 等價(jià)于 SQL 中的 "is null",比如 findByUsernameIsNull();
- IsNotNull --- 等價(jià)于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
- NotNull --- 與 IsNotNull 等價(jià);
- Like --- 等價(jià)于 SQL 中的 "like",比如 findByUsernameLike(String user);
- NotLike --- 等價(jià)于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
- OrderBy --- 等價(jià)于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
- Not --- 等價(jià)于 SQL 中的 "! =",比如 findByUsernameNot(String user);
- In --- 等價(jià)于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的參數(shù)可以是 Collection 類型,也可以是數(shù)組或者不定長(zhǎng)參數(shù);
- NotIn --- 等價(jià)于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的參數(shù)可以是 Collection 類型,也可以是數(shù)組或者不定長(zhǎng)參數(shù);
** 如果上面的也不能滿足?沒關(guān)系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的呢,也沒關(guān)系,使用@Modifying注解 **
@Modifying
@Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2")
public int increaseSalary(int after, int before);
10.想分頁(yè)查詢?cè)趺崔k?JPA也有強(qiáng)大的支持
可以看看我們寫的DAO中有哪些方法:
看見findAll(Pageable arg0)這個(gè)方法沒,通過傳一個(gè)Pageable的參數(shù)就可以了。可以看到dao里面還有其它常用的方法,如排序。
還有findAll(Specification<T> spec, Pageable pageable); Specification是什么,這里面可以封裝一些查詢條件。這里可以推薦一個(gè)開源的框架,springside?;蛘咦约簩懸膊浑y,如下圖:
看看我寫的service,如圖:
這個(gè)service就可以支持一個(gè)表的全部條件查詢,我就只需要修改我的頁(yè)面了,加一個(gè)條件查詢我只需要修改JSP(這里表示根據(jù)dictName字段去like查詢),爽吧,這樣單表的CRUD基本上可以很簡(jiǎn)單的寫個(gè)工具生成代碼了(后面也給整理出來)。比如:
<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
- 有可能目錄結(jié)構(gòu)中沒有src/main/java的目錄,如果沒有新建一個(gè)便可