SpringData之 介绍 和 Spring 整合 Hibernate
1. Spring Data课程中的技术介绍
(1) 什么是Hibernate?
Hibernate是一个开源的对象关系映射框架,它对JDBC进行了非常轻量级的封装,
它将POJO与数据表建立映射关系,是一个全自动化的ORM框架。
Hibernate可以自动生成sql语句,使程序员可以以对象的编程思维操作数据库。 Hibernate可以适用于任何使用JDBC的场景既可以在java的客户端程序使用,也可以在Servlet/Jsp的Web应用中使用。
最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
(2) 什么是JPA?
JPA是Java persistence API的缩写,中文名是Java持久层API。
是JDK 5.0注解或Xml方式描述“对象-数据表”的映射关系,并将运行期的实体对象持久化到数据库中。
Sun引入新的JPA ORM 规范的原因有两个:
1 简化现有Java EE和Java SE应用开发工作;
2 整合ORM技术,实现天下归一。
(3) 什么是Hibernate JPA?
Hibernate在3.2之后根据JPA规范提供了一套操作持久层的API。
(4) 什么是Spring Data?
Spring data的任务是为数据访问提供一个熟悉和一致的,基于Spring的编程模型,同时仍然保留底层数据存储的特殊特征。
(5) 什么是Spring Data JPA?
Spring Data JPA,更大的Spring Data系列的一部分,
使得轻松实现基于JPA的存储库变得很容易。
本模块涉及对基于JPA的数据访问层的增强支持。
它使得构建Spring支持的应用程序使用数据访问技术更加容易。
(6) 什么是Spring Data Redis
Spring Data Redis是更大的Spring Data系列的一部分,它提供了从Spring应用程序轻松配置和访问Redis的能力。它提供了用于与商店交互的低级和高级抽象,将用户从基础设施问题中解放出来。
2 Spring 整合 Hibernate
一、 创建项目
普通的java项目
二、 在配置文件中定义框架整合
<?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:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置读取 properties 文件的工具类 -->
<context:property-placeholder
location="classpath:jdbc.properties"/>
<!-- 配置 c3p0 数据库连接池 -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="driverClass" value="${jdbc.driver.class}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置 Hibernate 的 SeesionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- hibernateProperties 属性:配置与 hibernate 相关的内容,如显示
sql 语句,开启正向工程 -->
<property name="hibernateProperties">
<props>
<!-- 显示当前执行的 sql 语句 -->
<prop key="hibernate.show_sql">true</prop>
<!-- 开启正向工程 -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<!-- 扫描实体所在的包 -->
<property name="packagesToScan">
<list>
<value>com.bjsxt.pojo</value></list>
</property>
</bean>
<!-- 配置 Hibernate 的事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置开启注解事务处理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置 springIOC 的注解扫描 -->
<context:component-scan base-package="com.bjsxt"/>
</beans>
三、 通过 Hibernate 完成 CRUD 操作
1 创建数据库
2 编写实体类
(1) @Entity注解的作用是什么?
表示当前类是一个实体类。
(2) @Table注解的作用是什么?
1告诉Hibernate当前对象和名为name的数据表的有映射关系。
2同时如果开启了Hibernate的正向工程功能,生成的数据表名为name指定。
(3) @Id注解的作用是什么?
表示为数据表的主键
(4) @GeneratedValue注解的作用是什么?
指定主键生成策略,这里用的策略是自增长。
(5) @Column注解的作用是什么?
1告诉Hibernate当前对象的属性和数据表中的名为“Column中name”的字段是对应的,需要做映射处理。
2在正向工程中生成的数据表中也会生成这个字段。
@Entity
@Table(name="t_users")
public class Users implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)//strategy=Gene
rationType.IDENTITY 自增长
@Column(name="userid")
private Integer userid;
@Column(name="username")
private String username;
@Column(name="userage")
private Integer userage;
public Integer getUserid() {
return userid;
}
public void setUserid(Integer userid) {
this.userid = userid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getUserage() {
return userage;
}
public void setUserage(Integer userage) {
this.userage = userage;
}
}
3 编写 UserDao 接口与接口实现类
3.1修改配置文件,添加 HibernateTemplate 的配置
<!-- 配置 HiberanteTemplate 对象 -->
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
3.2接口实现类
(1) @Repository注解的作用是什么?
创建Dao层接口后实现接口时添加@Repository才能被Spring实例化出来。
Dao和实现类需要注意的:
这里我们需要使用Spring针对Hibernate操作的对象,封装了对Hibernate操作的模板叫HibernateTemplate。对于这个对象的使用有两种方式,
1 继承
2 再配置文件中配置,然后注解方式
<!-- 配置 HiberanteTemplate 对象 -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
好处是不用继承,如果这里需要继承其他类就不方便了。
不管哪种方式都要注意,HibernateTemplate这个对象需要sessionFactory。HibernateDaoSupport中有个属性叫sessionFactory。
@Repository
public class UsersDaoImpl implements UsersDao {
@Autowired
private HibernateTemplate hibernateTemplate;
@Override
public void insertUsers(Users users) {
this.hibernateTemplate.save(users);
}
@Override
public void updateUsers(Users users) {
this.hibernateTemplate.update(users);
}
@Override
public void deleteUsers(Users users) {
this.hibernateTemplate.delete(users);
}
@Override
public Users selectUsersById(Integer userid) {
return this.hibernateTemplate.get(Users.class, userid);
}
}
3.3编写测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UsersDaoImplTest {
@Autowired
private UsersDao usersDao;
/**
* 添加用户
*/
@Test
@Transactional// 在测试类对于事务提交方式默认的是回滚。
@Rollback(false)//取消自动回滚
public void testInsertUsers(){
Users users = new Users();
users.setUserage(20);
users.setUsername("张三");
this.usersDao.insertUsers(users);
}
/**
* 更新用户
*/
@Test
@Transactional
@Rollback(false)
public void testUpdateUsers(){
Users users = new Users();
users.setUserid(2);
users.setUserage(22);
users.setUsername("李四");
this.usersDao.updateUsers(users);
}
/**
* 根据 userid 查询用户
*/
@Test
public void testSelectUsersById(){
Users users = this.usersDao.selectUsersById(2);
System.out.println(users);}
/**
* 删除用户
*/
@Test
@Transactional
@Rollback(false)
public void testDeleteUsers(){
Users users = new Users();
users.setUserid(2);
this.usersDao.deleteUsers(users);
}
}
四、 HQL 查询
HQL:Hibernate Query Language
HQL 的语法:就是将原来的 sql 语句中的表与字段名称换成对象与属性的名称就可以了
(1) 什么是HQL语言?
HQL是Hibernate Query Language(Hibernate 查询语言)的缩写,提供更加丰富灵活、更为强大的查询能力;HQL更接近SQL语句查询语法。
Hibernate 查询语言(HQL)是一种面向对象的查询语言,类似于 SQL,但不是去对表和列进行操作,而是面向对象和它们的属性。 HQL 查询被 Hibernate 翻译为传统的 SQL 查询从而对数据库进行操作。
执行HQL查询的步骤:
1、获得HibernateSession对象
2、编写HQL语句
3、调用Session的createQuery方法创建查询对象
4、如果HQL语句包含参数,则调用Query的setXxx方法为参数赋值
5、调用Query对象的list等方法返回查询结果。
(2) HQL语言的语法是什么?
就是将原来的 sql 语句中的表与字段名称换成对象与属性的名称就可以了
(3) getCurrentSession与openSession的区别?
1、getCurrentSession返回的是当前session,而openSession是创建一个新的session
2、getCurrentSession返回的session,当Transaction在commit时会自动关闭,而openSession返回的session必须显示调用session.close()进行关闭。
1 添加查询方法
@Override
public List<Users> selectUserByName(String username) {
//getCurrentSession:当前 session 必须要有事务边界,且只能处理唯一
的一个事务。当事务提交或者回滚后 session 自动失效
//openSession:每次都会打开一个新的 session.加入每次使用多次。则获
得的是不同 session 对象。使用完毕后我们需要手动的调用 colse 方法关闭 session
Session session =
this.hibernateTemplate.getSessionFactory().getCurrentSession();
//sql:select * from t_users where username =
Query query = session.createQuery("from Users where username
= :abc");
Query queryTemp = query.setString("abc",username);
return queryTemp.list();
}
2 测试代码
/*** HQL 测试
*/
@Test
@Transactional
public void testSelectUserByName(){
List<Users> list = this.usersDao.selectUserByName("张三");
for (Users users : list) {
System.out.println(users);
}
}
五、 SQL 查询
1 添加查询方法
@Override
public List<Users> selectUserByNameUseSQL(String username) {
Session session =
this.hibernateTemplate.getSessionFactory().getCurrentSession();
Query query = session.createSQLQuery("select * from t_users
where username = ?").addEntity(Users.class).setString(0, username);
return query.list();
}
2 测试代码
@Test
@Transactional
public void testSelectUserByNameUseSQL(){
List<Users> list = this.usersDao.selectUserByNameUseSQL("张三
");
for (Users users : list) {
System.out.println(users);
}
}
六、 QBC 查询
QBC:Query By Criteria1 添加查询方法
@Override
public List<Users> selectUserByNameUseCriteria(String username) {
Session session =
this.hibernateTemplate.getSessionFactory().getCurrentSession();
//sql:select * from t_users where username = 张三
Criteria c = session.createCriteria(Users.class);
c.add(Restrictions.eq("username", username));
return c.list();
}
2 测试代码
@Test
@Transactional
public void testSelectUserByNameUseCriteria(){
List<Users> list = this.usersDao.selectUserByNameUseCriteria("
张三");
for (Users users : list) {
System.out.println(users);
}
}
SpringData 第二章 Spring 整合 Hibernate JPA
JPA:由 Sun 公司提供了一对对于持久层操作的标准(接口+文档)
Hibernate:是 Gavin King 开发的一套对于持久层操作的自动的 ORM 框架。
Hibernate JPA:是在 Hibernate3.2 版本那种提供了对于 JPA 的标准的实现。提供了一套按 照 JPA 标准来实现持久层开发的 API 。
Spring 整合 Hibernate JPA
1 创建项目:
2 在项目中导入 HIbernateJPA 相关的 jar 包
Hibernate-entitymanager-5.0.7-Final.jar
3 修改配置文件
<?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:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置读取 properties 文件的工具类 -->
<context:property-placeholder
location="classpath:jdbc.properties"/>
<!-- 配置 c3p0 数据库连接池 -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="driverClass" value="${jdbc.driver.class}"/><property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- Spring 整合 JPA 配置 EntityManagerFactory-->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBe
an">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- hibernate 相关的属性的注入 -->
<!-- 配置数据库类型 -->
<property name="database" value="MYSQL"/>
<!-- 正向工程 自动创建表 -->
<property name="generateDdl" value="true"/>
<!-- 显示执行的 SQL -->
<property name="showSql" value="true"/>
</bean>
</property>
<!-- 扫描实体的包 -->
<property name="packagesToScan">
<list>
<value>com.bjsxt.pojo</value>
</list>
</property>
</bean>
<!-- 配置 Hibernate 的事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory"
ref="entityManagerFactory"/>
</bean>
<!-- 配置开启注解事务处理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置 springIOC 的注解扫描 -->
<context:component-scan base-package="com.bjsxt"/>
</beans>
二、 Hibernate JPA 的 CRUD 操作
1 接口实现类
(1) @PersistenceContext注解的作用是什么?
注入的是实体管理器,执行持久化操作的,需要配置文件persistence.xml。
注入一堆保存实体类状态的数据结构,针对实体类的不同状态(四种,managedh或detached等)可以做出不同的反应(merge,persist等等),其实就是把数据从数据库里提出,然后在内存里处理的,再返回数据库的法则。
@Repository
public class UsersDaoImpl implements UsersDao {
@PersistenceContext(name="entityManagerFactory")
private EntityManager entityManager;
@Override
public void insertUsers(Users users) {
this.entityManager.persist(users);
}
@Override
public void updateUsers(Users users) {
this.entityManager.merge(users);
}
@Override
public void deleteUsers(Users users) {
Users u = this.selectUsersById(users.getUserid());
this.entityManager.remove(u);
}
@Override
public Users selectUsersById(Integer userid) {
return this.entityManager.find(Users.class, userid);
}
//Hibernate JPA 中的 HQL 语句
@Override
public List<Users> selectUserByName(String username) {
return this.entityManager.createQuery(" from Users where username = :abc")
.setParameter("abc", username).getResultList();
}
//HibernateJPA 中的 SQL 语句
@Override
public List<Users> selectUserByNameUseSQL(String username) {
return this.entityManager.createQuery("select * from t_users where username = :abc")
.setParameter("abc", username).getResultList();
}
//HibernateJPA 中 QBC 查询
@Override
public List<Users> selectUserByNameUseCriteria(String username) {
//CriteriaBuilder 对象:创建一个 CriteriaQuery,创建查询条件。
CriteriaBuilder builber = this.entityManager.getCriteriaBuilder();
//CriteriaQuery 对象:执行查询的 Criteria 对象
//select * from t_users
CriteriaQuery<Users> query = builber.createQuery(Users.class);
//获取要查询的实体类的对象
Root<Users> root = query.from(Users.class);
//封装查询条件
Predicate cate = builber.equal(root.get("username"), username);
//select * from t_users where username = 张三
query.where(cate);
//执行查询
TypedQuery<Users> typeQuery = this.entityManager.createQuery(query);
return typeQuery.getResultList();
}
}