最近写毕设的实验,就顺便把hibernate和spring配了一下,记录下来以后可能有用的到
Hibernate 配置
Hibernate.cfg.xml文件在intellij中配置数据源之后生成
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://localhost:3306/weibo_test</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">62050218</property>
<!-- Hibernate setting -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.autocommit">true</property>
<property name="javax.persistence.validation.mode">none</property>
<!-- c3p0 setting -->
<property name="hibernate.connection.provider_class">
org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider
</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<mapping class="org.mt.persistence.entity.CourseEntity"/>
<mapping class="org.mt.persistence.entity.StudentEntity"/>
<mapping class="org.mt.persistence.entity.StudentHasCourseEntity"/>
<!-- DB schema will be updated if needed -->
<!-- <property name="hbm2ddl.auto">update</property> -->
</session-factory>
</hibernate-configuration>
其中第一部分是数据源配置,第二部分是hibernate方言和自动提交等的配置,第三部分是c3P0数据源连接池的配置,之前本来是没有配这部分的,但是后来发现如果不在spring中直接配置数据源,而是继续使用hibernate配置文件的话,必须使用连接池才可以。c3p0配置下面的一部分是数据库实体配置,先通过mysql workbench 画ER图生成sql,再通过数据库逆向生成实体类还是比较方便的。
Spring 配置
spring-config.xml文件通过intellij自动生成
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="org.mt.persistence.dao"/>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
配置文件中sessionFactory通过配置文件引用hibernate的配置,componet-scan 配置了@Repository注解会扫描的包,使用了这个注解的bean不用在xml中配置就会自动被扫描为bean,bean id就是类名首字母小写。最后两段配置了spring中的transactionManager用于管理Hibernate事务,不然@Transactional注解无法用
@Repository
public class StudentDaoImp implements StudentDao{
private SessionFactory sessionFactory;
@Autowired
public StudentDaoImp(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
@Transactional
@Override
public void addStudent(StudentEntity student) {
getCurrentSession().save(student);
}
@Transactional
@Override
public StudentEntity loadStudent(Integer studentID) {
return (StudentEntity) getCurrentSession().get(StudentEntity.class, studentID);
}
@Transactional
@Override
public void updateStudent(StudentEntity student) {
getCurrentSession().update(student);
}
}
一个简单的利用@Repository 和@Transactional注解例子,通过这种方法定义bean必须定义接口,然后通过接口来调用spring 中的bean,这个倒是和spring一直崇尚的面向接口编程比较接近。@Autowired 是spring中的自动装配,@Transactional 在方法调用的时候都伴随着一个事务的开始与结束,结合hibernate3之后提供的线程绑定的currentSession,可以取代以前所用的HibernateTemplate。关于这几种注解的详细用法后面应该还是会花时间专门研究一下。
在整个实验的过程中,通过数据库反向生成实体的时候。多对多的关系生成的实体在实验过程中总是会报重复列的错误。
@javax.persistence.IdClass(org.mt.persistence.entity.StudentHasCourseEntityPK.class)
@javax.persistence.Table(name = "student_has_course", schema = "", catalog = "weibo_test")
@Entity
public class StudentHasCourseEntity {
private int studentId;
private int courseId;
private StudentEntity studentByStudentId;
private CourseEntity courseByCourseId;
@javax.persistence.Column(name = "student_id", nullable = false, insertable = true, updatable = true, length = 10, precision = 0)
@Id
public int getStudentId() {
return studentId;
}
public void setStudentId(int studentId) {
this.studentId = studentId;
}
@javax.persistence.Column(name = "course_id", nullable = false, insertable = true, updatable = true, length = 10, precision = 0)
@Id
public int getCourseId() {
return courseId;
}
public void setCourseId(int courseId) {
this.courseId = courseId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StudentHasCourseEntity that = (StudentHasCourseEntity) o;
if (courseId != that.courseId) return false;
if (studentId != that.studentId) return false;
return true;
}
@Override
public int hashCode() {
int result = studentId;
result = 31 * result + courseId;
return result;
}
@ManyToOne
@javax.persistence.JoinColumn(name = "student_id", referencedColumnName = "id", nullable = false,insertable = false,updatable = false)
public StudentEntity getStudentByStudentId() {
return studentByStudentId;
}
public void setStudentByStudentId(StudentEntity studentByStudentId) {
this.studentByStudentId = studentByStudentId;
}
@ManyToOne
@javax.persistence.JoinColumn(name = "course_id", referencedColumnName = "id", nullable = false,insertable = false,updatable = false)
public CourseEntity getCourseByCourseId() {
return courseByCourseId;
}
public void setCourseByCourseId(CourseEntity courseByCourseId) {
this.courseByCourseId = courseByCourseId;
}
}
看代码可以发现,多对多关系在数据库中被解析为两个一对多关系,并有一张额外的关系表,表中的两个元素为多对多关系表的ID,两个外键一起作为主键。通过自动生成的话,外键和主键定义重复确实会发生冲突。因此在外键定义中加上
insertable = false,updatable = false
可以保证插入的时候忽略外键,这里还是有点不清楚,后面还是应该再专门研究一下hibernate的实体配置
最后把项目maven的pom也贴上,免得以后配spring+hibernate的时候又忘了
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.mt</groupId>
<artifactId>testUser</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.version>3.2.4.RELEASE</org.springframework.version>
<version.hibernate>4.1.8.Final</version.hibernate>
<version.hibernate-validator>4.3.1.Final</version.hibernate-validator>
</properties>
<dependencies>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.24</version>
</dependency>
<!-- spring 配置 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Expression Language (depends on spring-core) Define this if you use
Spring Expression APIs (org.springframework.expression.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Bean Factory and JavaBeans utilities (depends on spring-core) Define
this if you use Spring Bean APIs (org.springframework.beans.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Aspect Oriented Programming (AOP) Framework (depends on spring-core,
spring-beans) Define this if you use Spring AOP APIs (org.springframework.aop.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Application Context (depends on spring-core, spring-expression, spring-aop,
spring-beans) This is the central artifact for Spring's Dependency Injection
Container and is generally always defined -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Various Application Context utilities, including EhCache, JavaMail,
Quartz, and Freemarker integration Define this if you need any of these integrations -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Transaction Management Abstraction (depends on spring-core, spring-beans,
spring-aop, spring-context) Define this if you use Spring Transactions or
DAO Exception Hierarchy (org.springframework.transaction.*/org.springframework.dao.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- JDBC Data Access Library (depends on spring-core, spring-beans, spring-context,
spring-tx) Define this if you use Spring's JdbcTemplate API (org.springframework.jdbc.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Object-to-Relation-Mapping (ORM) integration with Hibernate, JPA,
and iBatis. (depends on spring-core, spring-beans, spring-context, spring-tx)
Define this if you need ORM (org.springframework.orm.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Object-to-XML Mapping (OXM) abstraction and integration with JAXB,
JiBX, Castor, XStream, and XML Beans. (depends on spring-core, spring-beans,
spring-context) Define this if you need OXM (org.springframework.oxm.*) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- Support for testing Spring applications with tools such as JUnit and
TestNG This artifact is generally always defined with a 'test' scope for
the integration testing framework and unit testing stubs -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<!-- Hibernate 配置 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${version.hibernate}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${version.hibernate-validator}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>${version.hibernate-validator}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${version.hibernate}</version>
</dependency>
</dependencies>
</project>
另外,spring和hibernate的配置文件在使用maven来构建项目时应该放在maven的resource文件夹下