對象關系映射(Object Relational Mapping)
介紹
一種為了解決面向對象與關系數據庫存在的互不匹配的現象的技術
框架
- Hibernate
- Mybatis
....
好處
- 通用的資源管理
- 集成事務管理
- 統一常見的數據訪問異常
- 更容易測試
Spring集成Hibernate
集成思路
localSessionFactoryBean
作為Spring和Hibernate之間的介質,localSessionFactoryBean
可以作為中轉站,被Spring管理。
注入順序
- localSessionFactoryBean注入給DAO,
- DAO注入給Sevice
- Service注入給Controller
配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>cakessh</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 非web配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext.xml
</param-value>
</context-param>
<!-- 監聽容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Dispatcher請求分發 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- web相關配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 字符編碼過濾器 -->
<!-- 解決中文亂碼 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 打開一個session -->
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
配置spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 自動掃描且只掃描@Controller -->
<context:component-scan base-package="com.cakeonline">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 注解驅動 -->
<mvc:annotation-driven/>
<!-- 靜態資源直接響應 -->
<!-- 不需要Dispather分發 -->
<mvc:resources location="/static/" mapping="/static/**"/>
<!-- 定義JSP文件的位置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 文件上傳 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
</beans>
配置beans.xml(applicationContext.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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">
<description>Spring公共配置 </description>
<!-- 配置Spring上下文的注解 -->
<context:annotation-config />
<!-- 使用annotation 自動注冊bean, 並保證@Required、@Autowired的屬性被注入 -->
<context:component-scan base-package="com.cakeonline">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- hibernate -->
<!-- 屬性文件位置 -->
<context:property-placeholder location="classpath:*.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- localSessionFactoryBean -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.cakeonline.entity" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.useUnicode">${hibernate.useUnicode}</prop>
<prop key="hibernate.characterEncoding">${hibernate.characterEncoding}</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
</bean>
<!-- 使用annotation定義事務 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
</beans>
dbinfo.properties
#mysql
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/cakeonline_db?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=
#hibernate
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.format_sql=false
hibernate.useUnicode=true
hibernate.characterEncoding=utf-8
實體Bean
-
@Entity
-
@Table(name= "table_name")
-
@Id
-
@GenericGenerator(name = "myassigned", strategy = "assigned")
-
@GeneratedValue(generator = "myassigned")
自定義主鍵
代碼
@Entity
@Table(name = "tbl_user")
public class User {
private String email;
private String nickName;
private String password;
private Date registTime;
@Id
@GenericGenerator(name = "myassigned", strategy = "assigned")
@GeneratedValue(generator = "myassigned")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getRegistTime() {
return registTime;
}
public void setRegistTime(Date registTime) {
this.registTime = registTime;
}
}
DAO
-
@Repository
- 表明是數據持久層
- 命名方式與數據操作貼近
- saveUser
- updateUser
- deleteUser
- findByName
- findById
-
@Resource
依賴注入的注解
依賴注入sessionFactory
-
@Id
代碼
@Repository
public class UserDaoImpl {
@Resource
private SessionFactory sessionFactory;
/**
* saveUser
* updateUser
* deleteUser
* findByName
* findById
* @return
*/
public List<User> findAll(){
Query query = this.sessionFactory.getCurrentSession().createQuery("from User");
return query.list();
}
}
Service
-
@Serviec
- 表明是業務邏輯層
- 命名方式與實際業務貼近
- regist
- login
-
@Transactional(readOnly = true)
事務
-
@Resource
依賴注入的注解
依賴注入DAO
代碼
@Service
@Transactional(readOnly = true)
public class UserServiceImpl {
@Resource
private UserDaoImpl userDaoImpl;
/**
* regist
* login
* @return
*/
public List<User> listUsers(){
return this.userDaoImpl.findAll();
}
}
Controller
-
@Controller
注解表明是一個控制器
-
@RequestMapping("/controllername")
映射路徑
-
@Resource
依賴注入的注解
依賴注入Service
代碼
@Controller
@RequestMapping("/user")
public class UserController {
@Resource
private UserServiceImpl userServiceImpl;
@RequestMapping("/list")
public String list(Model model) {
List<User> users = this.userServiceImpl.listUsers();
model.addAttribute("users", users);
return "list";
}
}
過程
調用過程
- http請求(index.jsp)
- Controller控制器
- Service業務邏輯層
- DAO數據持久層
- sessionFactroy
- dataSource
- dbinfo.properties
依賴注入
- dataSource
- sessionFactroy
- DAO數據持久層
- Service業務邏輯層
- Controller控制器
數據校驗
數據校驗在項目中被廣泛應用,一般分為前端數據校驗和后端數據校驗
后端數據校驗可以采用JSR303進行數據校驗
JSR303是一個運行時數據校驗框架
它使得驗證邏輯從業務代碼中脫離出來
一般用於表單驗證
注解
注解 | 功能 |
---|---|
@NotNull | 注解元素必須是非空 |
@Null | 注解元素必須是空 |
@Digits | 驗證數字構成是否合法 |
@Future | 驗證是否在當前系統時間之后 |
@Past | 驗證是否在當前系統時間之前 |
@Max | 驗證值是否小於等於最大指定整數值 |
@Min | 驗證值是否大於等於最小指定整數值 |
@Pattern | 驗證字符串是否匹配指定的正則表達式 |
@Size | 驗證元素大小是否在指定范圍內 |
@DecimalMax | 驗證值是否小於等於最大指定小數值 |
@DecimalMin | 驗證值是否大於等於最小指定小數值 |
@AssertTrue | 被注解的元素必須為true |
@AssertFalse | 被注解的元素必須為false |
用法
Entity
public class User {
// @NotEmpty(message="登錄賬號不能為空!")
@NotEmpty
private String loginName;
// @Pattern(regexp="[0-9a-zA-Z]{6,30}", message="密碼是6-30個字符,必須是字母或數字組合!")
@Pattern(regexp="[0-9a-zA-Z]{6,30}")
private String password;
@NotEmpty(message="郵箱不能為空!")
@Email(message="郵件格式不正確!")
private String email;
@Past(message="生日不能晚於當前時間!")
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthday;
@Future(message="注冊時間不能早於當前時間!")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date registTime;
@DecimalMin(value="1000.00", message="工資必須大於1000")
@DecimalMax(value="10000.00", message="工資必須小於10000")
@NumberFormat(pattern="#,###.##")
private Double salary;
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Date getRegistTime() {
return registTime;
}
public void setRegistTime(Date registTime) {
this.registTime = registTime;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
Controller
method(@Valid 實體類,BindingResult bindingResult,
HttpSession session, Model model){
if(bindingResult.hasErrors()){
model.addAttribute("user", user);
return "user";
}else{
session.setAttribute("user", user);
return "center";
}
}