hibernate mysql 注解_【译】Spring 4 + Hibernate 4 + Mysql + Maven集成例子(注解 + XML)

前言

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

创建Hibernate实体

保存数据到mysql数据库中

在事务transaction内部执行增删改查操作

典型企业应用中不同层之间的交互

基于注解配置

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

涉及的技术及开发工具

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

工程结构目录

fca162710ecca58ae6b80728b98504bc.png

步骤一:往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

packagecom.websystique.spring.configuration;importjava.util.Properties;importjavax.sql.DataSource;importorg.hibernate.SessionFactory;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.PropertySource;importorg.springframework.core.env.Environment;importorg.springframework.jdbc.datasource.DriverManagerDataSource;importorg.springframework.orm.hibernate4.HibernateTransactionManager;importorg.springframework.orm.hibernate4.LocalSessionFactoryBean;importorg.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration

@EnableTransactionManagement

@ComponentScan({"com.websystique.spring.configuration"})

@PropertySource(value= { "classpath:application.properties"})public classHibernateConfiguration {

@AutowiredprivateEnvironment environment;

@BeanpublicLocalSessionFactoryBean sessionFactory() {

LocalSessionFactoryBean sessionFactory= newLocalSessionFactoryBean();

sessionFactory.setDataSource(dataSource());

sessionFactory.setPackagesToScan(new String[] { "com.websystique.spring.model"});

sessionFactory.setHibernateProperties(hibernateProperties());returnsessionFactory;

}

@BeanpublicDataSource dataSource() {

DriverManagerDataSource dataSource= newDriverManagerDataSource();

dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));

dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));

dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));

dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));returndataSource;

}privateProperties hibernateProperties() {

Properties properties= newProperties();

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"));returnproperties;

}

@Bean

@AutowiredpublicHibernateTransactionManager transactionManager(SessionFactory s) {

HibernateTransactionManager txManager= newHibernateTransactionManager();

txManager.setSessionFactory(s);returntxManager;

}

}

@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.Driver

jdbc.url = jdbc:mysql://localhost:3306/websystique

jdbc.username = myuser

jdbc.password = mypassword

hibernate.dialect = org.hibernate.dialect.MySQLDialect

hibernate.show_sql = false

hibernate.format_sql = false

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

http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd

http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd

http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

com.websystique.spring.model

${hibernate.dialect}

${hibernate.show_sql:false}

${hibernate.format_sql:false}

步骤三:Spring配置

com.websystique.spring.configuration.AppConfig

packagecom.websystique.spring.configuration;importorg.springframework.context.annotation.ComponentScan;importorg.springframework.context.annotation.Configuration;

@Configuration

@ComponentScan(basePackages= "com.websystique.spring")public classAppConfig {

}

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

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

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

对应的基于XML的配置

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

步骤四:DAO层

com.websystique.spring.dao.AbstractDao

packagecom.websystique.spring.dao;importorg.hibernate.Session;importorg.hibernate.SessionFactory;importorg.springframework.beans.factory.annotation.Autowired;public abstract classAbstractDao {

@AutowiredprivateSessionFactory sessionFactory;protectedSession getSession() {returnsessionFactory.getCurrentSession();

}public voidpersist(Object entity) {

getSession().persist(entity);

}public voiddelete(Object entity) {

getSession().delete(entity);

}

}

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

com.websystique.spring.dao.EmployeeDao

packagecom.websystique.spring.dao;importjava.util.List;importcom.websystique.spring.model.Employee;public interfaceEmployeeDao {voidsaveEmployee(Employee employee);

ListfindAllEmployees();voiddeleteEmployeeBySsn(String ssn);

Employee findBySsn(String ssn);voidupdateEmployee(Employee employee);

}

com.websystique.spring.dao.EmployeeDaoImpl

packagecom.websystique.spring.dao;importjava.util.List;importorg.hibernate.Criteria;importorg.hibernate.Query;importorg.hibernate.criterion.Restrictions;importorg.springframework.stereotype.Repository;importcom.websystique.spring.model.Employee;

@Repository("employeeDao")public class EmployeeDaoImpl extends AbstractDao implementsEmployeeDao{public voidsaveEmployee(Employee employee) {

persist(employee);

}

@SuppressWarnings("unchecked")public ListfindAllEmployees() {

Criteria criteria= getSession().createCriteria(Employee.class);return (List) criteria.list();

}public voiddeleteEmployeeBySsn(String ssn) {

Query query= getSession().createSQLQuery("delete from Employee where ssn = :ssn");

query.setString("ssn", ssn);

query.executeUpdate();

}publicEmployee findBySsn(String ssn){

Criteria criteria= getSession().createCriteria(Employee.class);

criteria.add(Restrictions.eq("ssn",ssn));return(Employee) criteria.uniqueResult();

}public voidupdateEmployee(Employee employee){

getSession().update(employee);

}

}

步骤五:添加Service层代码

com.websystique.spring.service.EmployeeService

packagecom.websystique.spring.service;importjava.util.List;importcom.websystique.spring.model.Employee;public interfaceEmployeeService {voidsaveEmployee(Employee employee);

ListfindAllEmployees();voiddeleteEmployeeBySsn(String ssn);

Employee findBySsn(String ssn);voidupdateEmployee(Employee employee);

}

com.websystique.spring.service.EmployeeServiceImpl

packagecom.websystique.spring.service;importjava.util.List;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;importorg.springframework.transaction.annotation.Transactional;importcom.websystique.spring.dao.EmployeeDao;importcom.websystique.spring.model.Employee;

@Service("employeeService")

@Transactionalpublic class EmployeeServiceImpl implementsEmployeeService{

@AutowiredprivateEmployeeDao dao;public voidsaveEmployee(Employee employee) {

dao.saveEmployee(employee);

}public ListfindAllEmployees() {returndao.findAllEmployees();

}public voiddeleteEmployeeBySsn(String ssn) {

dao.deleteEmployeeBySsn(ssn);

}publicEmployee findBySsn(String ssn) {returndao.findBySsn(ssn);

}public voidupdateEmployee(Employee employee){

dao.updateEmployee(employee);

}

}

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

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

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

com.websystique.spring.model.Employee

packagecom.websystique.spring.model;importjava.math.BigDecimal;importjavax.persistence.Column;importjavax.persistence.Entity;importjavax.persistence.GeneratedValue;importjavax.persistence.GenerationType;importjavax.persistence.Id;importjavax.persistence.Table;importorg.hibernate.annotations.Type;importorg.joda.time.LocalDate;

@Entity

@Table(name="EMPLOYEE")public classEmployee {

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)private intid;

@Column(name= "NAME", nullable = false)privateString name;

@Column(name= "JOINING_DATE", nullable = false)

@Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")privateLocalDate joiningDate;

@Column(name= "SALARY", nullable = false)privateBigDecimal salary;

@Column(name= "SSN", unique=true, nullable = false)privateString ssn;public intgetId() {returnid;

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

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicLocalDate getJoiningDate() {returnjoiningDate;

}public voidsetJoiningDate(LocalDate joiningDate) {this.joiningDate =joiningDate;

}publicBigDecimal getSalary() {returnsalary;

}public voidsetSalary(BigDecimal salary) {this.salary =salary;

}publicString getSsn() {returnssn;

}public voidsetSsn(String ssn) {this.ssn =ssn;

}

@Overridepublic inthashCode() {final int prime = 31;int result = 1;

result= prime * result +id;

result= prime * result + ((ssn == null) ? 0: ssn.hashCode());returnresult;

}

@Overridepublic booleanequals(Object obj) {if (this ==obj)return true;if (obj == null)return false;if (!(obj instanceofEmployee))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;

}

@OverridepublicString toString() {return "Employee [id=" + id + ", name=" + name + ", joiningDate="

+ joiningDate + ", salary=" + salary + ", ssn=" + ssn + "]";

}

}

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

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

CREATE TABLEEMPLOYEE(

idINT NOT NULLauto_increment,

nameVARCHAR(50) NOT NULL,

joining_date DATENOT NULL,

salaryDOUBLE NOT NULL,

ssnVARCHAR(30) NOT NULL UNIQUE,PRIMARY KEY(id)

);

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

packagecom.websystique.spring;importjava.math.BigDecimal;importjava.util.List;importorg.joda.time.LocalDate;importorg.springframework.context.annotation.AnnotationConfigApplicationContext;importorg.springframework.context.support.AbstractApplicationContext;importcom.websystique.spring.configuration.AppConfig;importcom.websystique.spring.model.Employee;importcom.websystique.spring.service.EmployeeService;public classAppMain {public static voidmain(String args[]) {

AbstractApplicationContext context= new AnnotationConfigApplicationContext(AppConfig.class);

EmployeeService service= (EmployeeService) context.getBean("employeeService");/** Create Employee1*/Employee employee1= newEmployee();

employee1.setName("Han Yenn");

employee1.setJoiningDate(new LocalDate(2010, 10, 10));

employee1.setSalary(new BigDecimal(10000));

employee1.setSsn("ssn00000001");/** Create Employee2*/Employee employee2= newEmployee();

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);

替换为

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值