Spring框架——ORM


对象关系映射(Object Relational Mapping)

介绍

一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术

框架

  • Hibernate
  • Mybatis
    ....

好处

  • 通用的资源管理
  • 集成事务管理
  • 统一常见的数据访问异常
  • 更容易测试

Spring集成Hibernate

集成思路

  1. localSessionFactoryBean作为Spring和Hibernate之间的介质,
  2. localSessionFactoryBean可以作为中转站,被Spring管理。

注入顺序

  • localSessionFactoryBean注入给DAO,
  • DAO注入给Sevice
  • Service注入给Controller

配置web.xml

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

  cakessh
	
		index.jsp
	
	
	
	
		contextConfigLocation
		
			classpath*:/applicationContext.xml
		
	
	
	
	
		org.springframework.web.context.ContextLoaderListener
	
	
	
	
		springmvc
		org.springframework.web.servlet.DispatcherServlet
		
			
			contextConfigLocation
			/WEB-INF/spring-mvc.xml
		
		1
	
	
		springmvc
		/
	
	
	
	
	
		CharacterEncodingFilter
		org.springframework.web.filter.CharacterEncodingFilter
		
			encoding
			utf-8
		
	
	
		CharacterEncodingFilter
		/*
	
	
	
	
		openSessionInView
		org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
	
	
		openSessionInView
		/*
	

配置spring-mvc.xml

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

 
	
	
		
	
	
	
	
	
	
	
    
	
	 
	
		
		
	
	
		
	
		
	


配置beans.xml(applicationContext.xml)

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

	Spring公共配置 

	
	
	
	
		
	
	
	
	
	
	
		
		
		
		
	


	
	
		
		
		
			
				${hibernate.dialect}
				${hibernate.show_sql}
				${hibernate.format_sql}
				${hibernate.useUnicode}
				${hibernate.characterEncoding}
				thread
			
		
	
	
	
		
	
	

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 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 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 users = this.userServiceImpl.listUsers();
		model.addAttribute("users", users);
		return "list";
	}

}

过程

调用过程

  1. http请求(index.jsp)
  2. Controller控制器
  3. Service业务逻辑层
  4. DAO数据持久层
  5. sessionFactroy
  6. dataSource
  7. dbinfo.properties

依赖注入

  1. dataSource
  2. sessionFactroy
  3. DAO数据持久层
  4. Service业务逻辑层
  5. 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";
      }
}