博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【译】Spring 4 + Hibernate 4 + Mysql + Maven集成例子(注解 + XML)
阅读量:6315 次
发布时间:2019-06-22

本文共 17298 字,大约阅读时间需要 57 分钟。

前言

译文链接:

本文将基于注解配置, 集成Spring 4和Hibernate 4,开发一个增删改查应用,涉及以下内容:

  1. 创建Hibernate实体
  2. 保存数据到mysql数据库中
  3. 在事务transaction内部执行增删改查操作
  4. 典型企业应用中不同层之间的交互
  5. 基于注解配置

当然,我们也会给出XML配置作为对比。

如果你的应用是基于Spring MVC开发,那么可以参考该链接:.

涉及的技术及开发工具

  • Spring 4.0.6.RELEASE
  • Hibernate Core 4.3.6.Final
  • MySQL Server 5.6
  • Joda-time 2.3
  • Maven 3
  • JDK 1.6
  • Eclipse JUNO Service Release 2

工程结构目录

步骤一:往pom.xml中添加依赖

4.0.0
com.websystique.spring
Spring4HibernateExample
1.0.0
jar
Spring4HibernateExample
4.0.6.RELEASE
4.3.6.Final
5.1.31
2.3
org.springframework
spring-core
${springframework.version}
org.springframework
spring-context
${springframework.version}
org.springframework
spring-tx
${springframework.version}
org.springframework
spring-orm
${springframework.version}
org.hibernate
hibernate-core
${hibernate.version}
mysql
mysql-connector-java
${mysql.connector.version}
joda-time
joda-time
${joda-time.version}
org.jadira.usertype
usertype.core
3.0.0.CR1
org.apache.maven.plugins
maven-compiler-plugin
3.2
1.6
1.6

很明显我们需要添加Spring、Hibernate和Mysql连接器相关依赖,另外,由于我们使用了joda-time库来处理时间,所以也引入了joda-time依赖。usertype-core库引入是为了提供数据库时间类型与joda-time LocalDate之间的映射。

步骤二:配置Hibernate

com.websystique.spring.configuration.HibernateConfiguration

package com.websystique.spring.configuration; import java.util.Properties; import javax.sql.DataSource; import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;import org.springframework.jdbc.datasource.DriverManagerDataSource;import org.springframework.orm.hibernate4.HibernateTransactionManager;import org.springframework.orm.hibernate4.LocalSessionFactoryBean;import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration@EnableTransactionManagement@ComponentScan({ "com.websystique.spring.configuration" })@PropertySource(value = { "classpath:application.properties" })public class HibernateConfiguration {     @Autowired    private Environment environment;     @Bean    public LocalSessionFactoryBean sessionFactory() {        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();        sessionFactory.setDataSource(dataSource());        sessionFactory.setPackagesToScan(new String[] { "com.websystique.spring.model" });        sessionFactory.setHibernateProperties(hibernateProperties());        return sessionFactory;     }         @Bean    public DataSource dataSource() {        DriverManagerDataSource dataSource = new DriverManagerDataSource();        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));        return dataSource;    }         private Properties hibernateProperties() {        Properties properties = new Properties();        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));        return properties;            }         @Bean    @Autowired    public HibernateTransactionManager transactionManager(SessionFactory s) {       HibernateTransactionManager txManager = new HibernateTransactionManager();       txManager.setSessionFactory(s);       return txManager;    }}

@Configuration注解表明该类包含了用@Bean标注的方法,这些被@Bean标注的方法可以生成bean并交由spring容器管理,在这里例子中,这个类代表了hibernate的配置。

@ComponentScan注解与xml配置中的“context:component-scan base-package="..."”等价,提供了扫描bean的包路径。

@EnableTransactionManagement注解与xml配置中Spring的tx:*命名空间等价,主要用于开启基于注解的事务管理。

@PropertySource注解用于在Spring运行时Environment中声明一组属性(在应用classpath路径下的properties文件中定义),可根据不同环境灵活改变属性值。

sessionFactory()方法创建了一个LocalSessionFactoryBean,与基于XML的配置类似,我们需要一个数据源dataSource和hibernate配置文件(如hibernate.properties)。

多亏了@PropertySource注解,我们可以从.properties文件中得到具体属性值,使用Spring的Environment接口获取对应项目的配置值。

一旦创建了SessionFactory,该bean将会被注入到transactionManager方法中,最终对sessionFactory创建的sessions提供事务支持功能。

如下是本文使用的属性配置文件:

/src/main/resources/application.properties

jdbc.driverClassName = com.mysql.jdbc.Driverjdbc.url = jdbc:mysql://localhost:3306/websystiquejdbc.username = myuserjdbc.password = mypasswordhibernate.dialect = org.hibernate.dialect.MySQLDialecthibernate.show_sql = falsehibernate.format_sql = false

另外,对应的基于XML配置如下

com.websystique.spring.model
${hibernate.dialect}
${hibernate.show_sql:false}
${hibernate.format_sql:false}

步骤三:Spring配置

com.websystique.spring.configuration.AppConfig

package com.websystique.spring.configuration; import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration; @Configuration@ComponentScan(basePackages = "com.websystique.spring")public class AppConfig { }

在我们这个示例中,即使该配置类内部是空的,但是使用了@ComponentScan注解,可以自动检测到对应包下所有的beans。

其实你可以完全去除以上的配置,将bean扫描功能放在application context级别去实现(main方法里)。

在成熟的应用里,你会发现使用配置类配置beans(如messageSource、PropertySourcesPlaceHolderConfigurer...)非常方便。

对应的基于XML的配置

以上就是关于本工程的所有配置了,现在,为了让工程能跑起来,我们还需要添加service、dao层,实体对象,数据库。

步骤四:DAO层

com.websystique.spring.dao.AbstractDao

package com.websystique.spring.dao; import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired; public abstract class AbstractDao {     @Autowired    private SessionFactory sessionFactory;     protected Session getSession() {        return sessionFactory.getCurrentSession();    }     public void persist(Object entity) {        getSession().persist(entity);    }     public void delete(Object entity) {        getSession().delete(entity);    }}

注意,我们在步骤二创建的SessionFactory会被自动装配到这里,这个类将作为基类用于执行数据库相关操作。

com.websystique.spring.dao.EmployeeDao

package com.websystique.spring.dao; import java.util.List; import com.websystique.spring.model.Employee; public interface EmployeeDao {     void saveEmployee(Employee employee);         List
findAllEmployees(); void deleteEmployeeBySsn(String ssn); Employee findBySsn(String ssn); void updateEmployee(Employee employee);}

com.websystique.spring.dao.EmployeeDaoImpl

package com.websystique.spring.dao; import java.util.List; import org.hibernate.Criteria;import org.hibernate.Query;import org.hibernate.criterion.Restrictions;import org.springframework.stereotype.Repository; import com.websystique.spring.model.Employee; @Repository("employeeDao")public class EmployeeDaoImpl extends AbstractDao implements EmployeeDao{     public void saveEmployee(Employee employee) {        persist(employee);    }     @SuppressWarnings("unchecked")    public List
findAllEmployees() { Criteria criteria = getSession().createCriteria(Employee.class); return (List
) criteria.list(); } public void deleteEmployeeBySsn(String ssn) { Query query = getSession().createSQLQuery("delete from Employee where ssn = :ssn"); query.setString("ssn", ssn); query.executeUpdate(); } public Employee findBySsn(String ssn){ Criteria criteria = getSession().createCriteria(Employee.class); criteria.add(Restrictions.eq("ssn",ssn)); return (Employee) criteria.uniqueResult(); } public void updateEmployee(Employee employee){ getSession().update(employee); } }

步骤五:添加Service层代码

com.websystique.spring.service.EmployeeService

package com.websystique.spring.service; import java.util.List; import com.websystique.spring.model.Employee; public interface EmployeeService {     void saveEmployee(Employee employee);     List
findAllEmployees(); void deleteEmployeeBySsn(String ssn); Employee findBySsn(String ssn); void updateEmployee(Employee employee);}

com.websystique.spring.service.EmployeeServiceImpl

package com.websystique.spring.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.websystique.spring.dao.EmployeeDao;import com.websystique.spring.model.Employee; @Service("employeeService")@Transactionalpublic class EmployeeServiceImpl implements EmployeeService{     @Autowired    private EmployeeDao dao;         public void saveEmployee(Employee employee) {        dao.saveEmployee(employee);    }     public List
findAllEmployees() { return dao.findAllEmployees(); } public void deleteEmployeeBySsn(String ssn) { dao.deleteEmployeeBySsn(ssn); } public Employee findBySsn(String ssn) { return dao.findBySsn(ssn); } public void updateEmployee(Employee employee){ dao.updateEmployee(employee); }}

以上比较引人注目的部分是@Transactional注解,配置了该注解的类会在每个类方法开启事务,并在方法结束的时候提交事务(或者在方法内部出错时回滚事务)。

注意,由于以上事务范围是方法级别的,我们在方法内部使用DAO,DAO方法会在同样的事物内部执行。

步骤六:创建实体类(POJO)

com.websystique.spring.model.Employee

package com.websystique.spring.model; import java.math.BigDecimal; import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table; import org.hibernate.annotations.Type;import org.joda.time.LocalDate; @Entity@Table(name="EMPLOYEE")public class Employee {     @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private int id;     @Column(name = "NAME", nullable = false)    private String name;     @Column(name = "JOINING_DATE", nullable = false)    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")    private LocalDate joiningDate;     @Column(name = "SALARY", nullable = false)    private BigDecimal salary;         @Column(name = "SSN", unique=true, nullable = false)    private String ssn;     public int getId() {        return id;    }     public void setId(int id) {        this.id = id;    }     public String getName() {        return name;    }     public void setName(String name) {        this.name = name;    }     public LocalDate getJoiningDate() {        return joiningDate;    }     public void setJoiningDate(LocalDate joiningDate) {        this.joiningDate = joiningDate;    }     public BigDecimal getSalary() {        return salary;    }     public void setSalary(BigDecimal salary) {        this.salary = salary;    }     public String getSsn() {        return ssn;    }     public void setSsn(String ssn) {        this.ssn = ssn;    }     @Override    public int hashCode() {        final int prime = 31;        int result = 1;        result = prime * result + id;        result = prime * result + ((ssn == null) ? 0 : ssn.hashCode());        return result;    }     @Override    public boolean equals(Object obj) {        if (this == obj)            return true;        if (obj == null)            return false;        if (!(obj instanceof Employee))            return false;        Employee other = (Employee) obj;        if (id != other.id)            return false;        if (ssn == null) {            if (other.ssn != null)                return false;        } else if (!ssn.equals(other.ssn))            return false;        return true;    }     @Override    public String toString() {        return "Employee [id=" + id + ", name=" + name + ", joiningDate="                + joiningDate + ", salary=" + salary + ", ssn=" + ssn + "]";    }                }

这是一个标准的实体类,基于JPA注解@Entity, @Table, @Column以及hibernate注解@Type(用于提供数据库类型与Joda-Time LocalDate的映射)。

步骤七:在数据库里创建Schema

CREATE TABLE EMPLOYEE(    id INT NOT NULL auto_increment,     name VARCHAR(50) NOT NULL,    joining_date DATE NOT NULL,    salary DOUBLE NOT NULL,    ssn VARCHAR(30) NOT NULL UNIQUE,    PRIMARY KEY (id));

步骤八:创建main方法执行程序

package com.websystique.spring; import java.math.BigDecimal;import java.util.List; import org.joda.time.LocalDate;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.AbstractApplicationContext; import com.websystique.spring.configuration.AppConfig;import com.websystique.spring.model.Employee;import com.websystique.spring.service.EmployeeService; public class AppMain {     public static void main(String args[]) {        AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);         EmployeeService service = (EmployeeService) context.getBean("employeeService");         /*         * Create Employee1         */        Employee employee1 = new Employee();        employee1.setName("Han Yenn");        employee1.setJoiningDate(new LocalDate(2010, 10, 10));        employee1.setSalary(new BigDecimal(10000));        employee1.setSsn("ssn00000001");         /*         * Create Employee2         */        Employee employee2 = new Employee();        employee2.setName("Dan Thomas");        employee2.setJoiningDate(new LocalDate(2012, 11, 11));        employee2.setSalary(new BigDecimal(20000));        employee2.setSsn("ssn00000002");         /*         * Persist both Employees         */        service.saveEmployee(employee1);        service.saveEmployee(employee2);         /*         * Get all employees list from database         */        List
employees = service.findAllEmployees(); for (Employee emp : employees) { System.out.println(emp); } /* * delete an employee */ service.deleteEmployeeBySsn("ssn00000002"); /* * update an employee */ Employee employee = service.findBySsn("ssn00000001"); employee.setSalary(new BigDecimal(50000)); service.updateEmployee(employee); /* * Get all employees list from database */ List
employeeList = service.findAllEmployees(); for (Employee emp : employeeList) { System.out.println(emp); } context.close(); }}

注意,假如你想删除AppConfig文件,那么只需将

AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

替换为

AnnotationConfigApplicationContext  context = new AnnotationConfigApplicationContext();
context.scan("com.websystique.spring");
context.refresh();
即可。
运行以上程序,结果如下:
Employee [id=1, name=Han Yenn, joiningDate=2010-10-10, salary=10000, ssn=ssn00000001]
Employee [id=2, name=Dan Thomas, joiningDate=2012-11-11, salary=20000, ssn=ssn00000002]
Employee [id=1, name=Han Yenn, joiningDate=2010-10-10, salary=50000, ssn=ssn00000001]

工程代码

注:源码EmployeeDaoImpl类中有一处错误,将26行表名Employee改成EMPLOYEE即可。

转载于:https://www.cnblogs.com/chenpi/p/6221790.html

你可能感兴趣的文章
Maven搭建SpringMVC+Mybatis项目详解
查看>>
关于量子理论:最初无意的简化,和一些人有意的强化和放大
查看>>
CentOS 6.9通过RPM安装EPEL源(http://dl.fedoraproject.org)
查看>>
“区块链”并没有什么特别之处
查看>>
没有功能需求设计文档?对不起,拒绝开发!
查看>>
4星|《先发影响力》:影响与反影响相关的有趣的心理学研究综述
查看>>
IE8调用window.open导出EXCEL文件题目
查看>>
python之 列表常用方法
查看>>
vue-cli脚手架的搭建
查看>>
在网页中加入百度搜索框实例代码
查看>>
在Flex中动态设置icon属性
查看>>
采集音频和摄像头视频并实时H264编码及AAC编码
查看>>
3星|《三联生活周刊》2017年39期:英国皇家助产士学会于2017年5月悄悄修改了政策,不再鼓励孕妇自然分娩了...
查看>>
高级Linux工程师常用软件清单
查看>>
堆排序算法
查看>>
folders.cgi占用系统大量资源
查看>>
路由器ospf动态路由配置
查看>>
zabbix监控安装与配置
查看>>
python 异常
查看>>
last_insert_id()获取mysql最后一条记录ID
查看>>