Spring整合HibernateHibernate JPASpring Data JPASpring Data Redis
Posted --->别先生<---
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring整合HibernateHibernate JPASpring Data JPASpring Data Redis相关的知识,希望对你有一定的参考价值。
环境说明,使用Jdk1.8版本,spring4.2.0.RELEASE版本、hibernate5.0.7.Final版本,spring-data-jpa-1.9.0.RELEASE版本、spring-data-redis-1.6.0.RELEASE版本。
1、Spring整合Hibernate的依赖jar包配置,修改pom.xml配置如下所示:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 5 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 6 <modelVersion>4.0.0</modelVersion> 7 8 <groupId>com.bie</groupId> 9 <artifactId>spring-hibernate</artifactId> 10 <version>1.0-SNAPSHOT</version> 11 12 <dependencies> 13 <!-- Spring IOC容器依赖的jar包 --> 14 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> 15 <dependency> 16 <groupId>org.springframework</groupId> 17 <artifactId>spring-context</artifactId> 18 <version>4.2.0.RELEASE</version> 19 </dependency> 20 <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> 21 <dependency> 22 <groupId>org.springframework</groupId> 23 <artifactId>spring-core</artifactId> 24 <version>4.2.0.RELEASE</version> 25 </dependency> 26 <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> 27 <dependency> 28 <groupId>org.springframework</groupId> 29 <artifactId>spring-beans</artifactId> 30 <version>4.2.0.RELEASE</version> 31 </dependency> 32 33 <!-- Spring AOP容器依赖的jar包 --> 34 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> 35 <dependency> 36 <groupId>org.springframework</groupId> 37 <artifactId>spring-aop</artifactId> 38 <version>4.2.0.RELEASE</version> 39 </dependency> 40 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> 41 <dependency> 42 <groupId>org.springframework</groupId> 43 <artifactId>spring-aspects</artifactId> 44 <version>4.2.0.RELEASE</version> 45 </dependency> 46 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> 47 <dependency> 48 <groupId>org.aspectj</groupId> 49 <artifactId>aspectjrt</artifactId> 50 <version>1.9.2</version> 51 </dependency> 52 53 <!-- Spring JDBC依赖的jar包 --> 54 <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> 55 <dependency> 56 <groupId>org.springframework</groupId> 57 <artifactId>spring-jdbc</artifactId> 58 <version>4.2.0.RELEASE</version> 59 </dependency> 60 <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> 61 <dependency> 62 <groupId>org.springframework</groupId> 63 <artifactId>spring-tx</artifactId> 64 <version>4.2.0.RELEASE</version> 65 </dependency> 66 67 <!-- Spring ORM依赖的jar包 --> 68 <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm --> 69 <dependency> 70 <groupId>org.springframework</groupId> 71 <artifactId>spring-orm</artifactId> 72 <version>4.2.0.RELEASE</version> 73 </dependency> 74 <!-- Spring 测试依赖的jar包 --> 75 <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> 76 <dependency> 77 <groupId>org.springframework</groupId> 78 <artifactId>spring-test</artifactId> 79 <version>4.2.0.RELEASE</version> 80 <scope>test</scope> 81 </dependency> 82 83 <!-- apache-logging依赖的jar包 --> 84 <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging --> 85 <dependency> 86 <groupId>commons-logging</groupId> 87 <artifactId>commons-logging</artifactId> 88 <version>1.1.1</version> 89 </dependency> 90 91 <!-- hibernate核心依赖jar包,此依赖下面包含8个依赖,共9个依赖包 --> 92 <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core --> 93 <dependency> 94 <groupId>org.hibernate</groupId> 95 <artifactId>hibernate-core</artifactId> 96 <version>5.0.7.Final</version> 97 </dependency> 98 99 <!-- mysql的依赖jar包 --> 100 <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> 101 <dependency> 102 <groupId>mysql</groupId> 103 <artifactId>mysql-connector-java</artifactId> 104 <version>5.1.6</version> 105 </dependency> 106 107 <!-- c3p0的依赖jar包 --> 108 <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --> 109 <dependency> 110 <groupId>com.mchange</groupId> 111 <artifactId>c3p0</artifactId> 112 <version>0.9.5.2</version> 113 </dependency> 114 <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 --> 115 <dependency> 116 <groupId>org.hibernate</groupId> 117 <artifactId>hibernate-c3p0</artifactId> 118 <version>5.0.7.Final</version> 119 </dependency> 120 121 <!-- hibernate-jpa的依赖jar包 --> 122 <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager --> 123 <dependency> 124 <groupId>org.hibernate</groupId> 125 <artifactId>hibernate-entitymanager</artifactId> 126 <version>5.0.7.Final</version> 127 </dependency> 128 129 <!-- junit的依赖jar包 --> 130 <!-- https://mvnrepository.com/artifact/junit/junit --> 131 <dependency> 132 <groupId>junit</groupId> 133 <artifactId>junit</artifactId> 134 <version>4.12</version> 135 <scope>test</scope> 136 </dependency> 137 138 139 </dependencies> 140 141 </project>
在配置文件applicationContext.xml中定义框架整合,将hibernate的配置整合到spring的applicationContext.xml的配置文件中。
1 jdbc.url=jdbc:mysql://localhost:3306/biehl?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC 2 jdbc.driver.class=com.mysql.jdbc.Driver 3 jdbc.username=root 4 jdbc.password=123456
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context.xsd 10 http://www.springframework.org/schema/tx 11 http://www.springframework.org/schema/tx/spring-tx.xsd"> 12 13 <!-- 1、配置读取properties文件的工具类 --> 14 <context:property-placeholder location="classpath:jdbc.properties"/> 15 16 <!-- 2、配置c3p0数据库连接池,ComboPooledDataSource创建数据库链接池,实例化该类。 --> 17 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 18 <property name="jdbcUrl" value="${jdbc.url}"/> 19 <property name="driverClass" value="${jdbc.driver.class}"/> 20 <property name="user" value="${jdbc.username}"/> 21 <property name="password" value="${jdbc.password}"/> 22 </bean> 23 24 <!-- 3、配置Hibernate的SeesionFactory,LocalSessionFactoryBean有3.x、4.x、5.x版本,根据自己的hibernate进行选择 --> 25 <!-- LocalSessionFactoryBean在spring启动的时候帮助我们初始化hibernate的sessionFactory对象。 --> 26 <!-- 注意:hibernate的上下文对象交由spring来进行管理,不再需要我们手动进行创建了的。 --> 27 <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> 28 <!-- 将c3p0的数据库链接池注入到sessionFactory对象实例中。 --> 29 <property name="dataSource" ref="dataSource"/> 30 <!-- hibernateProperties属性:配置与hibernate相关的内容,如显示sql语句,开启正向工程 --> 31 <property name="hibernateProperties"> 32 <props> 33 <!-- 显示当前执行的sql语句,后台打印执行的sql语句。 --> 34 <prop key="hibernate.show_sql">true</prop> 35 <!-- 开启正向工程,可以帮助生成数据表。 --> 36 <prop key="hibernate.hbm2ddl.auto">update</prop> 37 </props> 38 </property> 39 <!-- 扫描实体所在的包 --> 40 <property name="packagesToScan"> 41 <list> 42 <!-- 实体类所在的包。 --> 43 <value>com.bie.po</value> 44 </list> 45 </property> 46 </bean> 47 48 <!-- 4、配置Hibernate的事务管理器 --> 49 <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 50 <!-- 将spring创建的sessionFactory注入到事务管理器中 --> 51 <property name="sessionFactory" ref="sessionFactory"/> 52 </bean> 53 54 <!-- 5、配置开启注解事务处理,如果需要通过注解开启事务的话。开启注解就可以完成使用注解管理事务。 --> 55 <tx:annotation-driven transaction-manager="transactionManager"/> 56 57 <!-- 6、配置spring IOC的注解扫描 --> 58 <context:component-scan base-package="com.bie"/> 59 60 <!-- 7、配置HiberanteTemplate对象 --> 61 <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate"> 62 <!-- 将spring创建的sessionFactory注入HiberanteTemplate中 --> 63 <property name="sessionFactory" ref="sessionFactory"/> 64 </bean> 65 66 </beans>
创建实体类,如下所示:
1 package com.bie.po; 2 3 import javax.persistence.*; 4 5 @Entity // 表示当前类是实体类 6 @Table(name = "tb_users") // 告诉hibernate该实体类和数据表进行映射,如果开启了正向工程管理,name则是数据表的名称了。 7 public class Users { 8 9 @Id // 表示主键 10 @GeneratedValue(strategy = GenerationType.IDENTITY) // GenerationType.IDENTITY表示自增长的策略 11 @Column(name = "userId") // 告诉hibernate当前对象的属性和这个表里面的字段是对应的,需要做他俩的映射处理 12 // 同时,如果是正向工程,创建一个数据表的时候,这个数据表的一个字段的名称就是userId 13 private Integer id; 14 15 @Column(name = "userName") 16 private String name; 17 18 @Column(name = "userAge") 19 private Integer age; 20 21 public Integer getId() { 22 return id; 23 } 24 25 public void setId(Integer id) { 26 this.id = id; 27 } 28 29 public String getName() { 30 return name; 31 } 32 33 public void setName(String name) { 34 this.name = name; 35 } 36 37 public Integer getAge() { 38 return age; 39 } 40 41 public void setAge(Integer age) { 42 this.age = age; 43 } 44 45 @Override 46 public String toString() { 47 return "Users{" + 48 "id=" + id + 49 ", name=‘" + name + ‘‘‘ + 50 ", age=" + age + 51 ‘}‘; 52 } 53 54 public Users(String name) { 55 this.name = name; 56 } 57 58 public Users(String name, Integer age) { 59 this.name = name; 60 this.age = age; 61 } 62 63 public Users() { 64 } 65 }
创建dao层,数据交互层的接口和实现类。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 5 import java.util.List; 6 7 /** 8 * 9 */ 10 public interface UserDao { 11 12 /** 13 * 插入操作 14 * 15 * @param users 16 */ 17 public void insertUsers(Users users); 18 19 /** 20 * 修改操作 21 * 22 * @param users 23 */ 24 public void updateUsers(Users users); 25 26 /** 27 * 删除操作 28 * 29 * @param users 30 */ 31 public void deleteUsers(Users users); 32 33 /** 34 * 根据主键查询操作 35 * 36 * @param userid 37 * @return 38 */ 39 public Users selectUsersById(Integer userid); 40 41 /** 42 * 根据名称查询操作 43 * 44 * @param username 45 * @return 46 */ 47 public List<Users> selectUserByName(String username); 48 49 }
首先使用HQL来进行查询数据,如下所示:
HQL是Hibernate Query Language的缩写,HQL的语法,就是将原来的 sql 语句中的表与字段名称换成对象与属性的名称就可以了。
1 package com.bie.dao.impl; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.hibernate.Query; 6 import org.hibernate.Session; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.orm.hibernate5.HibernateTemplate; 9 import org.springframework.stereotype.Repository; 10 11 import java.util.List; 12 13 @Repository // 注入到IOC容器中 14 public class UserDaoImpl implements UserDao { 15 16 // Spring提供的操作hibernate的对象HibernateTemplate 17 // 这个HibernateTemplate里面封装了一些对hibernate的方法模板。 18 @Autowired 19 // 第一种实现是继承HibernateDaoSupport,如果使用继承方式的话,需要将sessionFactory注入到HibernateDaoSupport的sessionFactory属性。 20 // 第二种是在配置文件中进行配置,建议此种做法。 21 private HibernateTemplate hibernateTemplate; 22 23 24 @Override 25 public void insertUsers(Users users) { 26 this.hibernateTemplate.save(users); 27 } 28 29 @Override 30 public void updateUsers(Users users) { 31 this.hibernateTemplate.update(users); 32 } 33 34 @Override 35 public void deleteUsers(Users users) { 36 this.hibernateTemplate.delete(users); 37 } 38 39 @Override 40 public Users selectUsersById(Integer userid) { 41 return this.hibernateTemplate.get(Users.class, userid); 42 } 43 44 @Override 45 // @Transactional(readOnly = true) // getCurrentSession需要运行在一个事务边界中,所以需要开启事务。 46 public List<Users> selectUserByName(String username) { 47 // 获取session的两种方法。 48 // 方法一、getCurrentSession:当前session必须要有事务边界,且只能处理唯一的一个事务。 49 // 当事务提交或者回滚后session自动失效。 50 51 // 方法二、openSession:每次都会打开一个新的session.加入每次使用多次。则获得的是不同session对象。 52 // 使用完毕后我们需要手动的调用colse方法关闭session。 53 Session session = this.hibernateTemplate.getSessionFactory().getCurrentSession(); 54 //sql:select * from t_users where username =‘‘; 55 Query query = session.createQuery("from Users where name = :abc"); 56 Query queryTemp = query.setString("abc", username); 57 return queryTemp.list(); 58 } 59 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.test.annotation.Rollback; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 import org.springframework.transaction.annotation.Transactional; 12 13 import java.util.List; 14 15 /** 16 * 17 */ 18 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 19 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 20 public class UsersDaoImplTest { 21 22 @Autowired 23 private UserDao userDao; 24 25 /** 26 * 添加用户信息 27 */ 28 @Test 29 @Transactional // 在测试类对于事务提交方式默认的是回滚。 30 @Rollback(value = false) // 取消自动回滚 31 public void testInsertUsers() { 32 Users users = new Users("张飒飒", 25); 33 this.userDao.insertUsers(users); 34 } 35 36 /** 37 * 更新用户信息 38 */ 39 @Test 40 @Transactional 41 @Rollback(false) 42 public void testUpdateUsers() { 43 Users users = new Users("张飒飒", 22); 44 users.setId(1); 45 this.userDao.updateUsers(users); 46 } 47 48 /** 49 * 根据编号查询用户信息 50 */ 51 @Test 52 public void testSelectUsersById() { 53 Users users = this.userDao.selectUsersById(1); 54 System.out.println(users); 55 } 56 57 /** 58 * 删除用户信息 59 */ 60 @Test 61 @Transactional 62 @Rollback(false) 63 public void testDeleteUsers() { 64 Users users = new Users(); 65 users.setId(1); 66 this.userDao.deleteUsers(users); 67 } 68 69 @Test 70 @Transactional 71 public void testSelectUserByName() { 72 List<Users> usersList = this.userDao.selectUserByName("张飒飒"); 73 for (Users users : usersList) { 74 System.out.println(users.toString()); 75 } 76 } 77 }
使用SQL、QBC来进行数据的查询。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 5 import java.util.List; 6 7 /** 8 * 9 */ 10 public interface UserDao { 11 12 /** 13 * 插入操作 14 * 15 * @param users 16 */ 17 public void insertUsers(Users users); 18 19 /** 20 * 修改操作 21 * 22 * @param users 23 */ 24 public void updateUsers(Users users); 25 26 /** 27 * 删除操作 28 * 29 * @param users 30 */ 31 public void deleteUsers(Users users); 32 33 /** 34 * 根据主键查询操作 35 * 36 * @param userid 37 * @return 38 */ 39 public Users selectUsersById(Integer userid); 40 41 /** 42 * 根据名称查询操作 43 * 44 * @param username 45 * @return 46 */ 47 public List<Users> selectUserByName(String username); 48 49 /** 50 * 根据sql语句进行名称的查询。 51 * 52 * @param username 53 * @return 54 */ 55 List<Users> selectUserByNameUseSQL(String username); 56 57 /** 58 * QBC:Query By Criteria 59 * hibernate可以根据QBC放弃掉sql语句、hql的写法。 60 * 所有对数据库的操作都换成了对对象和方法的操作了。 61 * 62 * @param username 63 * @return 64 */ 65 List<Users> selectUserByNameUseCriteria(String username); 66 }
1 package com.bie.dao.impl; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.hibernate.Criteria; 6 import org.hibernate.Query; 7 import org.hibernate.Session; 8 import org.hibernate.criterion.Restrictions; 9 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.orm.hibernate5.HibernateTemplate; 11 import org.springframework.stereotype.Repository; 12 13 import java.util.List; 14 15 @Repository // 注入到IOC容器中 16 public class UserDaoImpl implements UserDao { 17 18 // Spring提供的操作hibernate的对象HibernateTemplate 19 // 这个HibernateTemplate里面封装了一些对hibernate的方法模板。 20 @Autowired 21 // 第一种实现是继承HibernateDaoSupport,如果使用继承方式的话,需要将sessionFactory注入到HibernateDaoSupport的sessionFactory属性。 22 // 第二种是在配置文件中进行配置,建议此种做法。 23 private HibernateTemplate hibernateTemplate; 24 25 26 @Override 27 public void insertUsers(Users users) { 28 this.hibernateTemplate.save(users); 29 } 30 31 @Override 32 public void updateUsers(Users users) { 33 this.hibernateTemplate.update(users); 34 } 35 36 @Override 37 public void deleteUsers(Users users) { 38 this.hibernateTemplate.delete(users); 39 } 40 41 @Override 42 public Users selectUsersById(Integer userid) { 43 return this.hibernateTemplate.get(Users.class, userid); 44 } 45 46 @Override 47 // @Transactional(readOnly = true) // getCurrentSession需要运行在一个事务边界中,所以需要开启事务。 48 public List<Users> selectUserByName(String username) { 49 // 获取session的两种方法。 50 // 方法一、getCurrentSession:当前session必须要有事务边界,且只能处理唯一的一个事务。 51 // 当事务提交或者回滚后session自动失效。 52 53 // 方法二、openSession:每次都会打开一个新的session.加入每次使用多次。则获得的是不同session对象。 54 // 使用完毕后我们需要手动的调用colse方法关闭session。 55 Session session = this.hibernateTemplate.getSessionFactory().getCurrentSession(); 56 //sql:select * from t_users where username =‘‘; 57 Query query = session.createQuery("from Users where name = :abc"); 58 Query queryTemp = query.setString("abc", username); 59 return queryTemp.list(); 60 } 61 62 @Override 63 // @Transactional(readOnly = true) // getCurrentSession需要运行在一个事务边界中,所以需要开启事务。 64 public List<Users> selectUserByNameUseSQL(String username) { 65 Session session = this.hibernateTemplate.getSessionFactory().getCurrentSession(); 66 // 使用原生的sql语句来进行查询操作。 67 Query query = session.createSQLQuery("select * from tb_users where userName = ?") 68 // sql执行的返回结果和那个实体类对象进行映射。 69 // HQL已经将数据表名称换成了实体类的名称。 70 .addEntity(Users.class) 71 .setString(0, username); 72 return query.list(); 73 } 74 75 @Override 76 // @Transactional(readOnly = true) // getCurrentSession需要运行在一个事务边界中,所以需要开启事务。 77 public List<Users> selectUserByNameUseCriteria(String username) { 78 Session session = this.hibernateTemplate.getSessionFactory().getCurrentSession(); 79 //sql:select * from t_users where username = ‘张三‘; 80 // 创建一个QBC:Query By Criteria 81 Criteria c = session.createCriteria(Users.class); 82 // 根据实体类的name字段属性进行查询。将需要查询的内容传递到参数二的位置上。 83 c.add(Restrictions.eq("name", username)); 84 return c.list(); 85 } 86 87 }
使用测试类进行测试,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.test.annotation.Rollback; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 import org.springframework.transaction.annotation.Transactional; 12 13 import java.util.List; 14 15 /** 16 * 17 */ 18 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 19 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 20 public class UsersDaoImplTest { 21 22 @Autowired 23 private UserDao userDao; 24 25 /** 26 * 添加用户信息 27 */ 28 @Test 29 @Transactional // 在测试类对于事务提交方式默认的是回滚。 30 @Rollback(value = false) // 取消自动回滚 31 public void testInsertUsers() { 32 Users users = new Users("张飒飒", 25); 33 this.userDao.insertUsers(users); 34 } 35 36 /** 37 * 更新用户信息 38 */ 39 @Test 40 @Transactional 41 @Rollback(false) 42 public void testUpdateUsers() { 43 Users users = new Users("张飒飒", 22); 44 users.setId(1); 45 this.userDao.updateUsers(users); 46 } 47 48 /** 49 * 根据编号查询用户信息 50 */ 51 @Test 52 public void testSelectUsersById() { 53 Users users = this.userDao.selectUsersById(1); 54 System.out.println(users); 55 } 56 57 /** 58 * 删除用户信息 59 */ 60 @Test 61 @Transactional 62 @Rollback(false) 63 public void testDeleteUsers() { 64 Users users = new Users(); 65 users.setId(1); 66 this.userDao.deleteUsers(users); 67 } 68 69 @Test 70 @Transactional 71 public void testSelectUserByName() { 72 List<Users> usersList = this.userDao.selectUserByName("张飒飒"); 73 for (Users users : usersList) { 74 System.out.println(users.toString()); 75 } 76 } 77 78 /** 79 * sql语句的查询测试。 80 */ 81 @Test 82 @Transactional 83 public void testSelectUserByNameUseSQL() { 84 List<Users> list = this.userDao.selectUserByNameUseSQL("张飒飒"); 85 for (Users users : list) { 86 System.out.println(users); 87 } 88 } 89 90 /** 91 * Criteria 测试 92 */ 93 @Test 94 @Transactional 95 public void testSelectUserByNameUseCriteria() { 96 List<Users> list = this.userDao.selectUserByNameUseCriteria("张飒飒"); 97 for (Users users : list) { 98 System.out.println(users); 99 } 100 } 101 102 }
2、JPA、Hibernate、Hibernate JPA的概念理解:
1)、JPA:由 Sun 公司提供了一个对于持久层操作的标准(该标准包含接口+文档,没有具体的实现) 。
2)、Hibernate:是 Gavin King 此人开发的一套对于持久层操作的自动的 ORM 框架。
3)、Hibernate JPA:是在 Hibernate3.2 版本中提供了对于 JPA 的标准的实现。提供了一套按照 JPA 标准来实现持久层开发的API。
1 <!-- hibernate-jpa的依赖jar包 --> 2 <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager --> 3 <dependency> 4 <groupId>org.hibernate</groupId> 5 <artifactId>hibernate-entitymanager</artifactId> 6 <version>5.0.7.Final</version> 7 </dependency>
修改spring的配置文件applicationContext.xml。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context 9 http://www.springframework.org/schema/context/spring-context.xsd 10 http://www.springframework.org/schema/tx 11 http://www.springframework.org/schema/tx/spring-tx.xsd"> 12 13 <!-- 1、配置读取properties文件的工具类 --> 14 <context:property-placeholder location="classpath:jdbc.properties"/> 15 16 <!-- 2、配置c3p0数据库连接池,ComboPooledDataSource创建数据库链接池,实例化该类。 --> 17 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 18 <property name="jdbcUrl" value="${jdbc.url}"/> 19 <property name="driverClass" value="${jdbc.driver.class}"/> 20 <property name="user" value="${jdbc.username}"/> 21 <property name="password" value="${jdbc.password}"/> 22 </bean> 23 24 <!-- 3、Spring 整合Hibernate JPA配置,EntityManagerFactory对象就是hibernate JPA帮助我们创建Hibernate JPA上下文的工厂 --> 25 <!-- LocalContainerEntityManagerFactoryBean帮助我们创建Hibernate JPA上下文的对象EntityManagerFactory --> 26 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 27 <!-- 将c3p0的数据库链接池注入到sessionFactory对象实例中。 --> 28 <property name="dataSource" ref="dataSource"/> 29 <!-- jpaVendorAdapter是一个接口,HibernateJpaVendorAdapter是实现类。 --> 30 <property name="jpaVendorAdapter"> 31 <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 32 <!-- hibernate 相关的属性的注入 --> <!-- 配置数据库类型 --> 33 <property name="database" value="MYSQL"/> 34 <!-- 正向工程 自动创建表 --> 35 <property name="generateDdl" value="true"/> 36 <!-- 显示执行的 SQL --> 37 <property name="showSql" value="true"/> 38 </bean> 39 </property> <!-- 扫描实体的包 --> 40 <property name="packagesToScan"> 41 <list> 42 <value>com.bie.po</value> 43 </list> 44 </property> 45 </bean> 46 47 <!-- 4、配置 Hibernate 的事务管理器 --> 48 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 49 <property name="entityManagerFactory" ref="entityManagerFactory"/> 50 </bean> 51 52 53 54 <!-- 5、配置开启注解事务处理,如果需要通过注解开启事务的话。开启注解就可以完成使用注解管理事务。 --> 55 <tx:annotation-driven transaction-manager="transactionManager"/> 56 57 <!-- 6、配置spring IOC的注解扫描 --> 58 <context:component-scan base-package="com.bie"/> 59 60 61 </beans>
创建dao层,数据交互层的接口和实现类。这里直接使用上面的实体类和dao层的接口,只是重新了dao层接口的实现类。
1 package com.bie.dao.impl; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.springframework.stereotype.Repository; 6 7 import javax.persistence.EntityManager; 8 import javax.persistence.PersistenceContext; 9 import javax.persistence.TypedQuery; 10 import javax.persistence.criteria.CriteriaBuilder; 11 import javax.persistence.criteria.CriteriaQuery; 12 import javax.persistence.criteria.Predicate; 13 import javax.persistence.criteria.Root; 14 import java.util.List; 15 16 @Repository // 注入到IOC容器中 17 public class UserDaoImpl implements UserDao { 18 19 // 使用hibernate JPA的对象进行方法的调用 20 @PersistenceContext(name = "entityManagerFactory") 21 private EntityManager entityManager; 22 23 24 @Override 25 public void insertUsers(Users users) { 26 this.entityManager.persist(users); 27 } 28 29 @Override 30 public void updateUsers(Users users) { 31 this.entityManager.merge(users); 32 } 33 34 @Override 35 public void deleteUsers(Users users) { 36 Users u = this.selectUsersById(users.getId()); 37 this.entityManager.remove(u); 38 } 39 40 @Override 41 public Users selectUsersById(Integer userid) { 42 return this.entityManager.find(Users.class, userid); 43 } 44 45 /** 46 * Hibernate JPA中的 HQL 语句 47 * 48 * @param username 49 * @return 50 */ 51 @Override 52 public List<Users> selectUserByName(String username) { 53 return this.entityManager.createQuery("from Users where name = :abc") 54 .setParameter("abc", username) 55 .getResultList(); 56 } 57 58 /** 59 * HibernateJPA 中的 SQL 语句 60 * 61 * @param username 62 * @return 63 */ 64 @Override 65 public List<Users> selectUserByNameUseSQL(String username) { 66 //在 Hibernate JPA 中 如果通过?方式来帮顶参数,那么他的查数是从 1 开始的。而 hibernate 中是从 0 开始的。 67 return this.entityManager 68 .createNativeQuery("select * from tb_users where userName = ?", Users.class) 69 .setParameter(1, username) 70 .getResultList(); 71 } 72 73 /** 74 * HibernateJPA 中 QBC 查询 75 * 76 * @param username 77 * @return 78 */ 79 @Override 80 public List<Users> selectUserByNameUseCriteria(String username) { 81 // CriteriaBuilder 对象:创建一个 CriteriaQuery,创建查询条件。 82 CriteriaBuilder builber = this.entityManager.getCriteriaBuilder(); 83 // CriteriaQuery 对象:执行查询的 Criteria 对象 84 // select * from tb_users 85 CriteriaQuery<Users> query = builber.createQuery(Users.class); 86 // 获取要查询的实体类的对象 87 Root<Users> root = query.from(Users.class); 88 // 封装查询条件 89 Predicate cate = builber.equal(root.get("name"), username); 90 // select * from t_users where username = ‘张三‘; 91 query.where(cate); 92 // 执行查询 93 TypedQuery<Users> typeQuery = this.entityManager.createQuery(query); 94 return typeQuery.getResultList(); 95 } 96 97 }
测试代码,可以直接使用上面的测试代码即可。
3、Spring Data JPA:Spring Data JPA 是 spring data 项目下的一个模块,提供了一套基于 JPA 标准操作数据库的简化方案,底层默认的是依赖 Hibernate JPA 来实现的。
3.1)、Spring Data JPA 的技术特点:我们只需要定义接口并集成 Spring Data JPA 中所提供的接 口就可以了,不需要编写接口实现类。Spring Data JPA是基于Hibernate JPA的,Hibernate JPA是依赖于Hibernate的。
1 <!-- spring-data-jpa的依赖jar包 --> 2 <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa --> 3 <dependency> 4 <groupId>org.springframework.data</groupId> 5 <artifactId>spring-data-jpa</artifactId> 6 <version>1.9.0.RELEASE</version> 7 </dependency> 8 <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> 9 <dependency> 10 <groupId>org.slf4j</groupId> 11 <artifactId>slf4j-log4j12</artifactId> 12 <version>1.7.2</version> 13 <scope>test</scope> 14 </dependency>
修改spring的配置文件applicationContext.xml。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:tx="http://www.springframework.org/schema/tx" 6 xmlns:jpa="http://www.springframework.org/schema/data/jpa" 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 http://www.springframework.org/schema/beans/spring-beans.xsd 9 http://www.springframework.org/schema/context 10 http://www.springframework.org/schema/context/spring-context.xsd 11 http://www.springframework.org/schema/data/jpa 12 http://www.springframework.org/schema/data/jpa/spring-jpa.xsd 13 http://www.springframework.org/schema/tx 14 http://www.springframework.org/schema/tx/spring-tx.xsd"> 15 16 <!-- 1、配置读取properties文件的工具类 --> 17 <context:property-placeholder location="classpath:jdbc.properties"/> 18 19 <!-- 2、配置c3p0数据库连接池,ComboPooledDataSource创建数据库链接池,实例化该类。 --> 20 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> 21 <property name="jdbcUrl" value="${jdbc.url}"/> 22 <property name="driverClass" value="${jdbc.driver.class}"/> 23 <property name="user" value="${jdbc.username}"/> 24 <property name="password" value="${jdbc.password}"/> 25 </bean> 26 27 <!-- 3、Spring 整合Hibernate JPA配置,EntityManagerFactory对象就是hibernate JPA帮助我们创建Hibernate JPA上下文的工厂 --> 28 <!-- LocalContainerEntityManagerFactoryBean帮助我们创建Hibernate JPA上下文的对象EntityManagerFactory --> 29 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 30 <!-- 将c3p0的数据库链接池注入到sessionFactory对象实例中。 --> 31 <property name="dataSource" ref="dataSource"/> 32 <!-- jpaVendorAdapter是一个接口,HibernateJpaVendorAdapter是实现类。 --> 33 <property name="jpaVendorAdapter"> 34 <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 35 <!-- hibernate 相关的属性的注入 --> <!-- 配置数据库类型 --> 36 <property name="database" value="MYSQL"/> 37 <!-- 正向工程 自动创建表 --> 38 <property name="generateDdl" value="true"/> 39 <!-- 显示执行的 SQL --> 40 <property name="showSql" value="true"/> 41 </bean> 42 </property> 43 <!-- 扫描实体的包 --> 44 <property name="packagesToScan"> 45 <list> 46 <value>com.bie.po</value> 47 </list> 48 </property> 49 </bean> 50 51 <!-- 4、配置 Hibernate 的事务管理器 --> 52 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 53 <property name="entityManagerFactory" ref="entityManagerFactory"/> 54 </bean> 55 56 <!-- 5、配置开启注解事务处理,如果需要通过注解开启事务的话。开启注解就可以完成使用注解管理事务。 --> 57 <tx:annotation-driven transaction-manager="transactionManager"/> 58 59 <!-- 6、配置spring IOC的注解扫描 --> 60 <context:component-scan base-package="com.bie"/> 61 62 63 <!-- Spring Data JPA 的配置 --> 64 <!-- base-package:扫描 dao 接口所在的包 --> 65 <jpa:repositories base-package="com.bie.dao"/> 66 67 </beans>
创建dao层的接口,继承JpaRepository<Users, Integer>,JpaRepository<Users, Integer>泛型参数一是实体类的名称,参数二是实体类的主键类型。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.jpa.repository.JpaRepository; 5 6 /** 7 * 使用Spring Data JPA 8 * <p> 9 * JpaRepository<Users, Integer>泛型参数一是实体类的名称,参数二是实体类的主键类型。 10 */ 11 public interface UserDao extends JpaRepository<Users, Integer> { 12 13 14 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.test.annotation.Rollback; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 import org.springframework.transaction.annotation.Transactional; 12 13 /** 14 * 15 */ 16 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 17 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 18 public class UsersDaoImplTest { 19 20 @Autowired 21 private UserDao userDao; 22 23 /** 24 * 添加用户信息 25 */ 26 @Test 27 @Transactional // 在测试类对于事务提交方式默认的是回滚。 28 @Rollback(value = false) // 取消自动回滚 29 public void testInsertUsers() { 30 Users users = new Users("张飒飒", 25); 31 this.userDao.save(users); 32 } 33 34 35 }
3.2)、Repository 接口是 Spring Data JPA 中为我们提供的所有接口中的顶层接口,Repository 提供了两种查询方式的支持。
1)、第一种,基于方法名称命名规则查询。方法命名规则:findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)。
关键字 | 方法命名 | sql where 子句 |
And | findByNameAndPwd | where name= ? and pwd =? |
Or | findByNameOrSex | where name= ? or sex=? |
Is,Equal | findById,findByIdEquals | where id= ? |
Between | findByIdBetween | where id between ? and ? |
LessThan | findByIdLessThan | where id < ? |
LessThanEqual | findByIdLessThanEqual | where id <= ? |
GreaterThan | findByIdGreaterThan | where id > ? |
GreaterThanEqual | findByIdGreaterThanEquals | where id > = ? |
After | findByIdAfter | where id > ? |
Before | findByIdBefore | where id < ? |
IsNull | findByNameIsNull | where name is null |
isNotNull,Not Null | findByNameNotNull | where name is not null |
Like | findByNameLike | where name like ? |
NotLike | findByNameNotLike | where name not like ? |
StartingWith | findByNameStartingWith | where name like ‘?%‘ |
EndingWith | findByNameEndingWith | where name like ‘%?‘ |
Containing | findByNameContaining | where name like ‘%?%‘ |
OrderBy | findByIdOrderByXDesc | where id=? order by x desc |
Not | findByNameNot | where name <> ? |
In | findByIdIn(Collection<?> c) | where id in (?) |
NotIn | findByIdNotIn(Collection<?> c) | where id not in (?) |
True、False | findByAaaTue、findByAaaFalse | where aaa = true、where aaa = false |
IgnoreCase | findByNameIgnoreCase | where UPPER(name)=UPPER(?) |
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.repository.Repository; 5 6 import java.util.List; 7 8 public interface UserDao extends Repository<Users, Integer> { 9 10 /** 11 * @param string 12 * @return 13 */ 14 List<Users> findByNameIs(String string); 15 16 /** 17 * @param string 18 * @return 19 */ 20 List<Users> findByNameLike(String string); 21 22 /** 23 * @param name 24 * @param age 25 * @return 26 */ 27 List<Users> findByNameAndAgeGreaterThanEqual(String name, Integer age); 28 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.test.context.ContextConfiguration; 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 11 import java.util.List; 12 13 /** 14 * 15 */ 16 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 17 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 18 public class UsersDaoImplTest { 19 20 @Autowired 21 private UserDao userDao; 22 23 /** 24 * 需求:使用用户名作为查询条件 25 */ 26 @Test 27 public void test1() { 28 // 判断相等的条件,有三种表示方式。 29 // 第一种什么都不写,默认的就是做相等判断。第二种是IS。第三种是Equal。 30 List<Users> list = this.userDao.findByNameIs("张飒飒"); 31 for (Users users : list) { 32 System.out.println(users); 33 } 34 } 35 36 /** 37 * 需求:根据用户姓名做 Like 处理 38 * <p> 39 * Like:条件关键字 40 */ 41 @Test 42 public void test2() { 43 List<Users> list = this.userDao.findByNameLike("张%"); 44 for (Users users : list) { 45 System.out.println(users); 46 } 47 } 48 49 /** 50 * 需求:查询名称为王五,并且他的年龄大于等于 22 岁 51 */ 52 @Test 53 public void test3() { 54 List<Users> list = this.userDao.findByNameAndAgeGreaterThanEqual("张飒飒", 22); 55 for (Users users : list) { 56 System.out.println(users); 57 } 58 } 59 60 61 }
2)、第二种,基于@Query 注解查询。
通过 JPQL 语句查询,JPQL是通过 Hibernate 的 HQL 演变过来的,它和 HQL 语法及其相似。测试代码,使用上面的测试代码即可。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.jpa.repository.Query; 5 import org.springframework.data.repository.Repository; 6 7 import java.util.List; 8 9 public interface UserDao extends Repository<Users, Integer> { 10 11 //使用@Query 注解查询 12 @Query(value = "from Users where name = ?") 13 List<Users> queryUserByNameUseJPQL(String name); 14 15 @Query("from Users where name like ?") 16 List<Users> queryUserByLikeNameUseJPQL(String name); 17 18 @Query("from Users where name = ? and age >= ?") 19 List<Users> queryUserByNameAndAge(String name, Integer age); 20 21 22 }
通过 SQL 语句查询。nativeQuery属性,默认的是false,表示不开启sql查询,是否对value中的语句做转义。如果是hql就不需要进行转义,如果是sql就需要进行转义的。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.jpa.repository.Query; 5 import org.springframework.data.repository.Repository; 6 7 import java.util.List; 8 9 public interface UserDao extends Repository<Users, Integer> { 10 11 // 使用@Query注解查询SQL 12 // nativeQuery:默认的是false,表示不开启sql查询,是否对value中的语句做转义。 13 @Query(value = "select * from tb_users where userName = ?", nativeQuery = true) 14 List<Users> queryUserByNameUseSQL(String name); 15 16 @Query(value = "select * from tb_users where userName like ?", nativeQuery = true) 17 List<Users> queryUserByLikeNameUseSQL(String name); 18 19 @Query(value = "select * from tb_users where userName = ? and userAge >= ?", nativeQuery = true) 20 List<Users> queryUserByNameAndAgeUseSQL(String name, Integer age); 21 }
通过@Query 注解完成数据更新,@Modifying 当前语句是一个更新语句。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.jpa.repository.Modifying; 5 import org.springframework.data.jpa.repository.Query; 6 import org.springframework.data.repository.Repository; 7 8 import java.util.List; 9 10 public interface UserDao extends Repository<Users, Integer> { 11 12 // 通过@Query注解完成数据更新 13 @Query("update Users set userAge = ? where userId = ?") 14 @Modifying //@Modifying 当前语句是一个更新语句 15 void updateUserAgeById(Integer age, Integer id); 16 }
3.3、CrudRepository 接口。该接口里面实现方法就自带事务了,不需要自己配置事务了。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.repository.CrudRepository; 5 6 /** 7 * CrudRepository接口 8 */ 9 public interface UserDao extends CrudRepository<Users, Integer> { 10 11 12 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.test.annotation.Rollback; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 import org.springframework.transaction.annotation.Transactional; 12 13 import java.util.ArrayList; 14 import java.util.List; 15 16 /** 17 * 18 */ 19 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 20 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 21 public class UsersDaoImplTest { 22 23 @Autowired 24 private UserDao userDao; 25 26 /** 27 * 添加单条数据 28 */ 29 @Test 30 public void test1() { 31 Users user = new Users("李四四", 21); 32 this.userDao.save(user); 33 } 34 35 /** 36 * 批量添加数据 37 */ 38 @Test 39 public void test2() { 40 Users user1 = new Users("李四四", 21); 41 Users user2 = new Users("王五五", 22); 42 List<Users> list = new ArrayList<>(); 43 list.add(user1); 44 list.add(user2); 45 this.userDao.save(list); 46 47 } 48 49 /** 50 * 根据 ID 查询单条数据 51 */ 52 @Test 53 public void test3() { 54 Users users = this.userDao.findOne(6); 55 System.out.println(users); 56 } 57 58 /** 59 * 查询全部数据 60 */ 61 @Test 62 public void test4() { 63 List<Users> list = (List<Users>) this.userDao.findAll(); 64 for (Users users : list) { 65 System.out.println(users); 66 } 67 } 68 69 /** 70 * 删除数据 71 */ 72 @Test 73 public void test5() { 74 this.userDao.delete(5); 75 } 76 77 /** 78 * 更新数据 方式一 79 */ 80 @Test 81 public void test6() { 82 Users user = this.userDao.findOne(6); 83 user.setName("亚瑟瑟"); 84 this.userDao.save(user); 85 } 86 87 /** 88 * 更新数据 方式二 89 */ 90 @Test 91 @Transactional 92 @Rollback(false) 93 public void test7() { 94 // 对象没有关闭,持久化状态的,对对象进行修改都是可以更新到数据库的。 95 Users user = this.userDao.findOne(6); 96 user.setName("王小小"); 97 } 98 99 }
3.4、PagingAndSortingRepository 接口,完成分页处理和排序处理,注意这里面的分页是查询全部的数据进行分页处理,是不带查询条件进行查询的。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.repository.PagingAndSortingRepository; 5 6 /** 7 * PagingAndSortingRepository 接口 8 */ 9 public interface UserDao extends PagingAndSortingRepository<Users, Integer> { 10 11 12 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.data.domain.Page; 9 import org.springframework.data.domain.PageRequest; 10 import org.springframework.data.domain.Pageable; 11 import org.springframework.data.domain.Sort; 12 import org.springframework.test.context.ContextConfiguration; 13 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 14 15 import java.util.List; 16 17 /** 18 * 19 */ 20 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 21 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 22 public class UsersDaoImplTest { 23 24 @Autowired 25 private UserDao userDao; 26 27 /** 28 * 分页,对数据表所有数据进行查询进行分页,是不带条件的分页查询。 29 */ 30 @Test 31 public void test1() { 32 // page,当前页的索引。注意索引都是从0开始的。 33 int page = 0; 34 // size,每页显示3条数据。 35 int size = 3; 36 Pageable pageable = new PageRequest(page, size); 37 Page<Users> p = this.userDao.findAll(pageable); 38 System.out.println("数据的总条数:" + p.getTotalElements()); 39 System.out.println("总页数:" + p.getTotalPages()); 40 List<Users> list = p.getContent(); 41 for (Users users : list) { 42 System.out.println(users); 43 } 44 } 45 46 47 /** 48 * 对单列做排序处理 49 */ 50 @Test 51 public void test2() { 52 // Sort代表了该对象封装了排序规则以及指定的排序字段(对象的属性来表示)。 53 // direction代表了排序规则。 54 // properties代表了指定做排序的实体类属性。 55 Sort sort = new Sort(Sort.Direction.DESC, "id"); 56 List<Users> list = (List<Users>) this.userDao.findAll(sort); 57 for (Users users : list) { 58 System.out.println(users); 59 } 60 } 61 62 /** 63 * 多列的排序处理 64 */ 65 @Test 66 public void test3() { 67 // Sort代表了该对象封装了排序规则以及指定的排序字段(对象的属性来表示)。 68 // direction代表了排序规则。 69 // properties代表了指定做排序的实体类属性。 70 Sort.Order order1 = new Sort.Order(Sort.Direction.DESC, "age"); 71 Sort.Order order2 = new Sort.Order(Sort.Direction.ASC, "name"); 72 Sort sort = new Sort(order1, order2); 73 List<Users> list = (List<Users>) this.userDao.findAll(sort); 74 for (Users users : list) { 75 System.out.println(users); 76 } 77 } 78 79 }
3.5、JpaRepository接口是我们开发时使用的最多的接口,其特点是可以帮助我们将其他接口的方法的返回值做适配处理,可以使得我们在开发时更方便的使用这些方法。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.jpa.repository.JpaRepository; 5 6 /** 7 * JpaRepository 接口 8 */ 9 public interface UserDao extends JpaRepository<Users, Integer> { 10 11 12 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.test.context.ContextConfiguration; 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 11 import java.util.List; 12 13 /** 14 * 15 */ 16 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 17 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 18 public class UsersDaoImplTest { 19 20 @Autowired 21 private UserDao userDao; 22 23 /** 24 * 查询全部数据 25 */ 26 @Test 27 public void test1() { 28 List<Users> list = this.userDao.findAll(); 29 for (Users users : list) { 30 System.out.println(users); 31 } 32 } 33 34 }
3.6、JpaSpecificationExecutor 接口,完成多条件查询,并且支持分页与排序。此接口不可以单独使用,需要配合着Jpa中的其他接口配合使用的,因为该接口没有继承于其他接口。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.jpa.repository.JpaRepository; 5 import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 6 7 /** 8 * JpaSpecificationExecutor 接口 9 * 注意:JpaSpecificationExecutor<Users>:不能单独使用,需要配合着 jpa 中的其他接口一起使用 10 */ 11 public interface UserDao extends JpaRepository<Users, Integer>, JpaSpecificationExecutor<Users> { 12 13 14 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.data.domain.Page; 9 import org.springframework.data.domain.PageRequest; 10 import org.springframework.data.domain.Pageable; 11 import org.springframework.data.domain.Sort; 12 import org.springframework.data.jpa.domain.Specification; 13 import org.springframework.test.context.ContextConfiguration; 14 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 15 16 import javax.persistence.criteria.CriteriaBuilder; 17 import javax.persistence.criteria.CriteriaQuery; 18 import javax.persistence.criteria.Predicate; 19 import javax.persistence.criteria.Root; 20 import java.util.ArrayList; 21 import java.util.List; 22 23 /** 24 * 25 */ 26 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 27 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 28 public class UsersDaoImplTest { 29 30 @Autowired 31 private UserDao userDao; 32 33 /** 34 * 需求:根据用户姓名查询数据 35 */ 36 @Test 37 public void test1() { 38 39 Specification<Users> specification = new Specification<Users>() { 40 /** 41 * 42 * @param root 根对象。封装了查询条件的对象 43 * @param query 定义了一个基本的查询.一般不使用 44 * @param cb 创建一个查询条件 45 * @return Predicate:定义了查询条件 46 */ 47 @Override 48 public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 49 Predicate pre = cb.equal(root.get("name"), "王五五"); 50 return pre; 51 } 52 53 }; 54 List<Users> list = this.userDao.findAll(specification); 55 for (Users users : list) { 56 System.out.println(users); 57 } 58 } 59 60 /** 61 * 多条件查询 方式一 62 * 需求:使用用户姓名以及年龄查询数据 63 */ 64 @Test 65 public void test2() { 66 Specification<Users> specification = new Specification<Users>() { 67 68 @Override 69 public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 70 List<Predicate> list = new ArrayList<>(); 71 list.add(cb.equal(root.get("name"), "王五五")); 72 list.add(cb.equal(root.get("age"), 22)); 73 //此时条件之间是没有任何关系的。 74 Predicate[] arr = new Predicate[list.size()]; 75 return cb.and(list.toArray(arr)); 76 } 77 78 }; 79 List<Users> list = this.userDao.findAll(specification); 80 for (Users users : list) { 81 System.out.println(users); 82 } 83 } 84 85 /** 86 * 多条件查询 方式二 87 * 需求:使用用户姓名或者年龄查询数据 88 */ 89 @Test 90 public void test3() { 91 Specification<Users> specification = new Specification<Users>() { 92 93 @Override 94 public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 95 return cb.or(cb.equal(root.get("name"), "王五五"), cb.equal(root.get("age"), 22)); 96 } 97 98 }; 99 List<Users> list = this.userDao.findAll(specification); 100 for (Users users : list) { 101 System.out.println(users); 102 } 103 } 104 105 /** 106 * 需求:查询王姓用户,并且做分页处理 107 */ 108 @Test 109 public void test4() { 110 // 条件 111 Specification<Users> specification = new Specification<Users>() { 112 113 @Override 114 public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 115 return cb.like(root.get("name").as(String.class), "王%"); 116 } 117 118 }; 119 120 // 分页 121 Pageable pageable = new PageRequest(0, 2); 122 Page<Users> page = this.userDao.findAll(specification, pageable); 123 System.out.println("总条数:" + page.getTotalElements()); 124 System.out.println("总页数:" + page.getTotalPages()); 125 List<Users> list = page.getContent(); 126 for (Users users : list) { 127 System.out.println(users); 128 } 129 } 130 131 /** 132 * 需求:查询数据库中王姓的用户,并且根据用户id做倒序排序 133 */ 134 @Test 135 public void test5() { 136 //条件 137 Specification<Users> specification = new Specification<Users>() { 138 139 @Override 140 public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 141 return cb.like(root.get("name").as(String.class), "王%"); 142 } 143 144 }; 145 // 排序 146 Sort sort = new Sort(Sort.Direction.DESC, "id"); 147 List<Users> list = this.userDao.findAll(specification, sort); 148 for (Users users : list) { 149 System.out.println(users); 150 } 151 } 152 153 /** 154 * 需求:查询数据库中王姓的用户,做分页处理,并且根据用户id做倒序排序 155 */ 156 @Test 157 public void test6() { 158 // 排序等定义 159 Sort sort = new Sort(Sort.Direction.DESC, "id"); 160 // 分页的定义 161 Pageable pageable = new PageRequest(0, 2, sort); 162 163 // 查询条件 164 Specification<Users> specification = new Specification<Users>() { 165 166 @Override 167 public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) { 168 return cb.like(root.get("name").as(String.class), "王%"); 169 } 170 171 }; 172 Page<Users> page = this.userDao.findAll(specification, pageable); 173 System.out.println("总条数:" + page.getTotalElements()); 174 System.out.println("总页数:" + page.getTotalPages()); 175 List<Users> list = page.getContent(); 176 for (Users users : list) { 177 System.out.println(users); 178 } 179 } 180 181 182 }
3.7、用户自定义 Repository 接口,如果上面Jpa接口满足不了需求,可以进行自定义 Repository 接口。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 5 /** 6 * 用户自定义接口 7 */ 8 public interface UsersRepository { 9 10 /** 11 * 根据用户主键信息查询用户信息 12 * 13 * @param userid 14 * @return 15 */ 16 public Users findUserById(Integer userid); 17 18 }
定义自己的业务接口,然后继承自己的自定义Jpa接口。
1 package com.bie.dao; 2 3 import com.bie.po.Users; 4 import org.springframework.data.jpa.repository.JpaRepository; 5 import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 6 7 /** 8 * 用户自定义接口 9 */ 10 public interface UserDao extends JpaRepository<Users, Integer>, JpaSpecificationExecutor<Users>, UsersRepository { 11 12 13 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Users; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.test.context.ContextConfiguration; 9 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 10 11 /** 12 * 13 */ 14 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 15 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 16 public class UsersDaoImplTest { 17 18 @Autowired 19 private UserDao userDao; 20 21 22 @Test 23 public void test7() { 24 Users users = this.userDao.findUserById(6); 25 System.out.println(users); 26 } 27 28 }
3.7、Spring data Jpa关联映射操作。
需求:是用户与角色的一对一的关联关系,一个用户只能有一个角色,一个角色只能分配给一个用户
1 package com.bie.po; 2 3 import javax.persistence.*; 4 5 @Entity // 表示当前类是实体类 6 @Table(name = "tb_users") // 告诉hibernate该实体类和数据表进行映射,如果开启了正向工程管理,name则是数据表的名称了。 7 public class Users { 8 9 @Id // 表示主键 10 @GeneratedValue(strategy = GenerationType.IDENTITY) // GenerationType.IDENTITY表示自增长的策略 11 @Column(name = "userId") // 告诉hibernate当前对象的属性和这个表里面的字段是对应的,需要做他俩的映射处理 12 // 同时,如果是正向工程,创建一个数据表的时候,这个数据表的一个字段的名称就是userId 13 private Integer id; 14 15 @Column(name = "userName") 16 private String name; 17 18 @Column(name = "userAge") 19 private Integer age; 20 21 @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 22 // @JoinColumn:就是维护一个外键,该外键就是用户和角色关联的一个键 23 @JoinColumn(name = "roles_id") 24 private Roles roles;// 该roles对象就表示当前对象所对应的角色。 25 26 public Integer getId() { 27 return id; 28 } 29 30 public void setId(Integer id) { 31 this.id = id; 32 } 33 34 public String getName() { 35 return name; 36 } 37 38 public void setName(String name) { 39 this.name = name; 40 } 41 42 public Integer getAge() { 43 return age; 44 } 45 46 public void setAge(Integer age) { 47 this.age = age; 48 } 49 50 @Override 51 public String toString() { 52 return "Users{" + 53 "id=" + id + 54 ", name=‘" + name + ‘‘‘ + 55 ", age=" + age + 56 ‘}‘; 57 } 58 59 public Users(String name) { 60 this.name = name; 61 } 62 63 public Users(String name, Integer age) { 64 this.name = name; 65 this.age = age; 66 } 67 68 public Users() { 69 } 70 71 public Roles getRoles() { 72 return roles; 73 } 74 75 public void setRoles(Roles roles) { 76 this.roles = roles; 77 } 78 }
角色的实体类,如下所示:
1 package com.bie.po; 2 3 import javax.persistence.*; 4 5 @Entity 6 @Table(name = "tb_roles") 7 public class Roles { 8 9 10 @Id 11 @GeneratedValue(strategy = GenerationType.IDENTITY) 12 @Column(name = "roleId") 13 private Integer roleId;// 角色编号 14 15 @Column(name = "roleName") 16 private String roleName;// 角色名称 17 18 // 注意,这里面的mappedBy的值就是用户实体类里面的角色的对象实例名称 19 // 将那个对象关联进行,去关联跟这个用户里面相同的角色对应的用户。 20 @OneToOne(mappedBy = "roles") 21 private Users users;// 表示当前角色对应的用户 22 23 public Integer getRoleId() { 24 return roleId; 25 } 26 27 public void setRoleId(Integer roleId) { 28 this.roleId = roleId; 29 } 30 31 public String getRoleName() { 32 return roleName; 33 } 34 35 public void setRoleName(String roleName) { 36 this.roleName = roleName; 37 } 38 39 public Roles(String roleName) { 40 this.roleName = roleName; 41 } 42 43 @Override 44 public String toString() { 45 return "Roles{" + 46 "roleId=" + roleId + 47 ", roleName=‘" + roleName + ‘‘‘ + 48 ‘}‘; 49 } 50 51 public Roles() { 52 } 53 54 public Users getUsers() { 55 return users; 56 } 57 58 public void setUsers(Users users) { 59 this.users = users; 60 } 61 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Roles; 5 import com.bie.po.Users; 6 import org.junit.Test; 7 import org.junit.runner.RunWith; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 12 /** 13 * 14 */ 15 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 16 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 17 public class UsersDaoImplTest { 18 19 @Autowired 20 private UserDao userDao; 21 22 // 添加用户的同时,添加角色 23 24 /** 25 * 一对一关联关系的添加 26 */ 27 @Test 28 public void testSave() { 29 // 创建一个用户 30 Users users = new Users("admin", 22); 31 32 // 创建一个角色 33 Roles roles = new Roles("管理员"); 34 35 // 关联,建立双向关系 36 users.setRoles(roles); 37 roles.setUsers(users); 38 39 40 // 新增,插入用户的时候进行级联操作。 41 this.userDao.save(users); 42 } 43 44 /** 45 * 一对一关联关系的查询 46 */ 47 @Test 48 public void testSelect() { 49 Users users = this.userDao.findOne(1); 50 System.out.println(users.toString()); 51 System.out.println(users.getRoles().toString()); 52 } 53 }
需求:一对多的关联关系,需求是用户与角色的一对多的关联关系,一个用户只能有一个角色,一个角色只能分配给多个用户,用户对用户是一对多的关联关系。
1 package com.bie.po; 2 3 import javax.persistence.*; 4 5 @Entity // 表示该类是实体类 6 @Table(name = "tb_users") // 表示该实体类和数据表进行映射,name表示实体类和数据表进行映射 7 // 如果使用的是正向工程的话,name属性的值表示的是数据表的表名称。 8 public class Users { 9 10 @Id // 表示该字段是主键 11 @GeneratedValue(strategy = GenerationType.IDENTITY) // 主键的生成策略 12 @Column(name = "id") // 表示实体类的字段和数据表的字段进行映射的关系,如果是正向工程的话,name的值就是数据表的字段名称 13 private Integer id;// 用户编号 14 15 @Column(name = "name") 16 private String name;// 用户姓名 17 18 @Column(name = "age") 19 private Integer age;// 用户年龄 20 21 @Column(name = "address") 22 private String address;// 用户地址 23 24 // 用户是多方,角色是一方,所以一个用户只能分配一个角色 25 @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER) // 用户对角色,多对一关系 26 @JoinColumn(name = "roles_id") // 该注解的作用就是为了维护一个外键,外键在Users这一侧 27 // 可以通过正向工程在数据表新增一个字段。 28 private Roles roles; 29 30 31 // alt + insert来生成构造器、settergetter等等方法 32 public Integer getId() { 33 return id; 34 } 35 36 public void setId(Integer id) { 37 this.id = id; 38 } 39 40 public String getName() { 41 return name; 42 } 43 44 public void setName(String name) { 45 this.name = name; 46 } 47 48 public Integer getAge() { 49 return age; 50 } 51 52 public void setAge(Integer age) { 53 this.age = age; 54 } 55 56 public String getAddress() { 57 return address; 58 } 59 60 public void setAddress(String address) { 61 this.address = address; 62 } 63 64 @Override 65 public String toString() { 66 return "Users{" + 67 "id=" + id + 68 ", name=‘" + name + ‘‘‘ + 69 ", age=" + age + 70 ", address=‘" + address + ‘‘‘ + 71 ‘}‘; 72 } 73 74 public Users(String name, Integer age, String address) { 75 this.name = name; 76 this.age = age; 77 this.address = address; 78 } 79 80 81 public Users() { 82 } 83 84 public Roles getRoles() { 85 return roles; 86 } 87 88 public void setRoles(Roles roles) { 89 this.roles = roles; 90 } 91 92 }
角色的实体类,如下所示:
1 package com.bie.po; 2 3 import javax.persistence.*; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 @Entity 8 @Table(name = "tb_roles") 9 public class Roles { 10 11 @Id 12 @GeneratedValue(strategy = GenerationType.IDENTITY) 13 @Column(name = "roleId") 14 private Integer roleId;// 角色编号 15 16 @Column(name = "roleName") 17 private String roleName;// 角色名称 18 19 // 角色是多的方式,一个角色可以分配给多个用户 20 @OneToMany(mappedBy = "roles") 21 //表示一对多的关系,mappedBy表示向Set集合放Users,放的是当前roles相同的,外键和主键相同的 22 // 表示外键和主键相同的,做在角色表里面角色和那个用户之间的描述。 23 private Set<Users> usersSet = new HashSet<Users>(); 24 25 public Integer getRoleId() { 26 return roleId; 27 } 28 29 public void setRoleId(Integer roleId) { 30 this.roleId = roleId; 31 } 32 33 public String getRoleName() { 34 return roleName; 35 } 36 37 public void setRoleName(String roleName) { 38 this.roleName = roleName; 39 } 40 41 @Override 42 public String toString() { 43 return "Roles{" + 44 "roleId=" + roleId + 45 ", roleName=‘" + roleName + ‘‘‘ + 46 ‘}‘; 47 } 48 49 public Roles(String roleName) { 50 this.roleName = roleName; 51 } 52 53 public Roles() { 54 } 55 56 public Set<Users> getUsersSet() { 57 return usersSet; 58 } 59 60 public void setUsersSet(Set<Users> usersSet) { 61 this.usersSet = usersSet; 62 } 63 64 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.UserDao; 4 import com.bie.po.Roles; 5 import com.bie.po.Users; 6 import org.junit.Test; 7 import org.junit.runner.RunWith; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 12 /** 13 * 14 */ 15 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 16 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 17 public class UsersDaoImplTest { 18 19 @Autowired 20 private UserDao userDao; 21 22 // 添加用户的同时,添加角色 23 24 /** 25 * 一对多关联关系的添加 26 */ 27 @Test 28 public void testSave() { 29 // 创建一个用户 30 Users users = new Users("admin", 22, "北京市西城区"); 31 32 // 创建一个角色 33 Roles roles = new Roles("管理员"); 34 35 // 关联,建立双向关系 36 users.setRoles(roles); 37 roles.getUsersSet().add(users); 38 39 40 // 新增,插入用户的时候进行级联操作。 41 this.userDao.save(users); 42 } 43 44 /** 45 * 一对多关联关系的查询 46 */ 47 @Test 48 public void testSelect() { 49 Users users = this.userDao.findOne(5); 50 System.out.println(users.toString()); 51 System.out.println(users.getRoles().toString()); 52 } 53 }
如果出现下面的错误:
可以使用@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)。
Spring Data JPA中有四种Cascade 类型:
1)、PERSIST:持久保存拥有的实体,也会持久保存该实体的属于相关数据。
2)、MERGE:将分离的实体重新合并到活动的持久性上下文时,也会合并该实体的所有数据。
3)、REMOVE:删除一个实体时候,也删除该实体的所有数据。
4)、ALL:以上都适用。
Spring Data JPA中有两种fetch 类型:
1)、FetchType.EAGE:如果是EAGER,那么表示取出这条数据时,它关联的数据也同时取出放入内存中。
2)、FetchType.LAZY:如果是LAZY,那么取出这条数据时,它关联的数据并不取出来,在同一个session中,什么时候要用,就什么时候取(再次访问数据库)。
1 org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.bie.po.Users.roles -> com.bie.po.Roles; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.bie.po.Users.roles -> com.bie.po.Roles 2 3 at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:381) 4 at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223) 5 at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521) 6 at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761) 7 at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) 8 at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485) 9 at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291) 10 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 11 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 12 at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) 13 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 14 at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:119) 15 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 16 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) 17 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 18 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) 19 at com.sun.proxy.$Proxy33.save(Unknown Source) 20 at com.bie.test.UsersDaoImplTest.testSave(UsersDaoImplTest.java:40) 21 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 22 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 23 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 24 at java.lang.reflect.Method.invoke(Method.java:498) 25 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 26 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 27 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 28 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 29 at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 30 at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:85) 31 at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:86) 32 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 33 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:241) 34 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87) 35 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 36 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 37 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 38 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 39 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 40 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 41 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 42 at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 43 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) 44 at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 45 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 46 at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 47 at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 48 at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) 49 Caused by: java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.bie.po.Users.roles -> com.bie.po.Roles 50 at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1689) 51 at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602) 52 at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1608) 53 at org.hibernate.jpa.internal.EntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(EntityManagerImpl.java:235) 54 at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2967) 55 at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339) 56 at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) 57 at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147) 58 at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) 59 at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) 60 at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65) 61 at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61) 62 at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517) 63 ... 43 more 64 Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.bie.po.Users.roles -> com.bie.po.Roles 65 at org.hibernate.engine.spi.CascadingActions$8.noCascade(CascadingActions.java:379) 66 at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126) 67 at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:150) 68 at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:141) 69 at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:74) 70 at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38) 71 at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282) 72 at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465) 73 at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963) 74 ... 51 more 75 76 77 Process finished with exit code -1
需求:多对多的关联关系,需求是角色与菜单的多对多的关联关系,一个角色可以有多个菜单,一个菜单可以有多个角色。
1 package com.bie.dao; 2 3 import com.bie.po.Roles; 4 import org.springframework.data.jpa.repository.JpaRepository; 5 6 public interface RoleDao extends JpaRepository<Roles, Integer> { 7 8 9 }
角色信息的实体类,代码如下所示。
1 package com.bie.po; 2 3 import javax.persistence.*; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 @Entity 8 @Table(name = "tb_roles") 9 public class Roles { 10 11 12 @Id 13 @GeneratedValue(strategy = GenerationType.IDENTITY) 14 @Column(name = "roleId") 15 private Integer roleId;// 角色编号 16 17 @Column(name = "roleName") 18 private String roleName;// 角色名称 19 20 @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) // 放弃延迟加载,改为立即加载。 21 // @JoinTable:配置中间表信息 22 // joinColumns:建立当前表在中间表中的外键字段 23 @JoinTable(name = "t_roles_menus", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "menu_id")) 24 private Set<Menus> menus = new HashSet<>(); 25 26 public Integer getRoleId() { 27 return roleId; 28 } 29 30 public void setRoleId(Integer roleId) { 31 this.roleId = roleId; 32 } 33 34 public String getRoleName() { 35 return roleName; 36 } 37 38 public void setRoleName(String roleName) { 39 this.roleName = roleName; 40 } 41 42 public Roles(String roleName) { 43 this.roleName = roleName; 44 } 45 46 @Override 47 public String toString() { 48 return "Roles{" + 49 "roleId=" + roleId + 50 ", roleName=‘" + roleName + ‘‘‘ + 51 ‘}‘; 52 } 53 54 public Roles() { 55 } 56 57 public Set<Menus> getMenus() { 58 return menus; 59 } 60 61 public void setMenus(Set<Menus> menus) { 62 this.menus = menus; 63 } 64 }
菜单信息的实体类,如下所示:
1 package com.bie.po; 2 3 import javax.persistence.*; 4 import java.util.HashSet; 5 import java.util.Set; 6 7 @Entity 8 @Table(name = "tb_menus") 9 public class Menus { 10 11 @Id 12 @GeneratedValue(strategy = GenerationType.IDENTITY) 13 @Column(name = "menusid") 14 private Integer menusId;// 菜单编号 15 16 @Column(name = "menusname") 17 private String menusName;// 菜单名称 18 19 @Column(name = "menusUrl") 20 private String menusurl;// 菜单路径 21 22 @Column(name = "fatherid") 23 private Integer fatherId;// 父菜单 24 25 // 一个菜单可以对应多个角色,一个角色可以对应多个菜单。 26 @ManyToMany(mappedBy = "menus") 27 private Set<Roles> roles = new HashSet<>(); 28 29 public Menus() { 30 } 31 32 public Menus(String menusName, Integer fatherId, String menusurl) { 33 this.menusName = menusName; 34 this.menusurl = menusurl; 35 this.fatherId = fatherId; 36 } 37 38 @Override 39 public String toString() { 40 return "Menus{" + 41 "menusId=" + menusId + 42 ", menusName=‘" + menusName + ‘‘‘ + 43 ", menusurl=‘" + menusurl + ‘‘‘ + 44 ", fatherId=" + fatherId + 45 ", roles=" + roles + 46 ‘}‘; 47 } 48 49 public Integer getMenusId() { 50 return menusId; 51 } 52 53 public void setMenusId(Integer menusId) { 54 this.menusId = menusId; 55 } 56 57 public String getMenusName() { 58 return menusName; 59 } 60 61 public void setMenusName(String menusName) { 62 this.menusName = menusName; 63 } 64 65 public String getMenusurl() { 66 return menusurl; 67 } 68 69 public void setMenusurl(String menusurl) { 70 this.menusurl = menusurl; 71 } 72 73 public Integer getFatherId() { 74 return fatherId; 75 } 76 77 public void setFatherId(Integer fatherId) { 78 this.fatherId = fatherId; 79 } 80 81 public Set<Roles> getRoles() { 82 return roles; 83 } 84 85 public void setRoles(Set<Roles> roles) { 86 this.roles = roles; 87 } 88 }
测试代码,如下所示:
1 package com.bie.test; 2 3 import com.bie.dao.RoleDao; 4 import com.bie.po.Menus; 5 import com.bie.po.Roles; 6 import org.junit.Test; 7 import org.junit.runner.RunWith; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.test.context.ContextConfiguration; 10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 11 12 import java.util.Set; 13 14 /** 15 * 16 */ 17 @RunWith(SpringJUnit4ClassRunner.class) // spring与junit的整合。 18 @ContextConfiguration("classpath:applicationContext.xml") // 加载spring的配置文件applicationContext.xml 19 public class UsersDaoImplTest { 20 21 @Autowired 22 private RoleDao roleDao; 23 24 25 /** 26 * 添加角色同时添加菜单 27 */ 28 @Test 29 public void test1() { 30 // 创建角色对象 31 Roles roles = new Roles("超级管理员"); 32 // 创建菜单对象 XXX 管理平台 --->用户管理 33 Menus menus = new Menus("哈哈哈管理平台", -1, "null"); 34 35 // 用户管理菜单 36 Menus menus1 = new Menus("用户管理平台", -1, "null"); 37 38 // 建立关系 39 roles.getMenus().add(menus); 40 roles.getMenus().add(menus1); 41 menus.getRoles().add(roles); 42 menus1.getRoles().add(roles); 43 44 // 保存数据 45 this.roleDao.save(roles); 46 } 47 48 /** 49 * 查询 Roles 50 */ 51 @Test 52 public void test2() { 53 Roles roles = this.roleDao.findOne(1); 54 System.out.println("角色信息:" + roles); 55 Set<Menus> menus = roles.getMenus(); 56 for (Menus menus2 : menus) { 57 System.out.println("菜单信息:" + menus2); 58 } 59 } 60 61 }
4、Spring Data Redis帮助我们更方便,更容易操作Redis。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 5 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 6 <modelVersion>4.0.0</modelVersion> 7 8 <groupId>com.bie</groupId> 9 <artifactId>spring-redis</artifactId> 10 <version>1.0-SNAPSHOT</version> 11 12 <dependencies> 13 <!-- Spring IOC容器依赖的jar包 --> 14 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> 15 <dependency> 16 <groupId>org.springframework</groupId> 17 <artifactId>spring-context</artifactId> 18 <version>4.2.0.RELEASE</version> 19 </dependency> 20 <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> 21 <dependency> 22 <groupId>org.springframework</groupId> 23 <artifactId>spring-core</artifactId> 24 <version>4.2.0.RELEASE</version> 25 </dependency> 26 <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> 27 <dependency> 28 <groupId>org.springframework</groupId> 29 <artifactId>spring-beans</artifactId> 30 <version>4.2.0.RELEASE</version> 31 </dependency> 32 33 <!-- Spring AOP容器依赖的jar包 --> 34 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --> 35 <dependency> 36 <groupId>org.springframework</groupId> 37 <artifactId>spring-aop</artifactId> 38 <version>4.2.0.RELEASE</version> 39 </dependency> 40 <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects --> 41 <dependency> 42 <groupId>org.springframework</groupId> 43 <artifactId>spring-aspects</artifactId> 44 <version>4.2.0.RELEASE</version> 45 </dependency> 46 <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> 47 <dependency> 48 <groupId>org.aspectj</groupId> 49 <artifactId>aspectjrt</artifactId> 50 <version>1.9.2</version> 51 </dependency> 52 53 <!-- Spring JDBC依赖的jar包 --> 54 <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> 55 <dependency> 56 <groupId>org.springframework</groupId> 57 <artifactId>spring-jdbc</artifactId> 58 <version>4.2.0.RELEASE</version> 59 </dependency> 60 <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> 61 <dependency> 62 <groupId>org.springframework</groupId> 63 <artifactId>spring-tx</artifactId> 64 <version>4.2.0.RELEASE</version> 65 </dependency> 66 67 <!-- apache-logging依赖的jar包 --> 68 <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging --> 69 <dependency> 70 <groupId>commons-logging</groupId> 71 <artifactId>commons-logging</artifactId> 72 <version>1.1.1</version> 73 </dependency> 74 75 <!-- Spring 测试依赖的jar包 --> 76 <!-- https://mvnrepository.com/artifact/org.springframework/spring-test --> 77 <dependency> 78 <groupId>org.springframework</groupId> 79 <artifactId>spring-test</artifactId> 80 <version>4.2.0.RELEASE</version> 81 <scope>test</scope> 82 </dependency> 83 84 <!-- junit的依赖jar包 --> 85 <!-- https://mvnrepository.com/artifact/junit/junit --> 86 <dependency> 87 <groupId>junit</groupId> 88 <artifactId>junit</artifactId> 89 <version>4.12</version> 90 <scope>test</scope> 91 </dependency> 92 93 <!-- redis的依赖包、Spring Data JPA的依赖包。 --> 94 <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis --> 95 <dependency> 96 <groupId>org.springframework.data</groupId> 97 <artifactId>spring-data-redis</artifactId> 98 <version>1.6.0.RELEASE</version> 99 </dependency> 100 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> 101 <dependency> 102 <groupId>redis.clients</groupId> 103 <artifactId>jedis</artifactId> 104 <version>2.7.2</version> 105 </dependency> 106 107 108 </dependencies> 109 110 </project>
Spring整合SpringDataRedis整合配置文件application.xml,配置redis连接信息的redis.properties。
1 # 最大连接数 2 redis.pool.maxtTotal=20 3 # 最大空闲数 4 redis.pool.maxIdle=10 5 # 最小空闲数 6 redis.pool.minIdle=5 7 8 # redis的ip地址 9 redis.hostname=192.168.110.140 10 # redis的端口号 11 redis.port=6379
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context.xsd"> 9 10 <!-- 配置读取properties文件的工具类 --> 11 <context:property-placeholder location="classpath:redis.properties"/> 12 13 <!-- Jedis连接池 --> 14 <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> 15 <property name="maxTotal" value="${redis.pool.maxtTotal}"/> 16 <property name="maxIdle" value="${redis.pool.maxIdle}"/> 17 <property name="minIdle" value="${redis.pool.minIdle}"/> 18 </bean> 19 20 <!-- Jedis连接工厂:创建Jedis对象的工厂 --> 21 <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> 22 <!-- IP地址 --> 23 <property name="hostName" value="${redis.hostname}"/> 24 <!-- 端口 --> 25 <property name="port" value="${redis.port}"/> 26 <!-- 连接池 --> 27 <property name="poolConfig" ref="poolConfig"/> 28 </bean> 29 30 <!-- Redis模板对象:是SpringDataRedis提供的用户操作Redis的对象 --> 31 <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> 32 <!-- 模板对象注入Jedisd的连接工厂,连接工厂注入redis的ip地址信息,端口号 --> 33 <property name="connectionFactory" ref="jedisConnectionFactory"/> 34 <!-- 默认的序列化器:序列化器就是根据规则将存储的数据中的key与value做字符串的序列化处理 --> 35 <!-- keySerializer、valueSerializer:对应的是Redis中的String类型 --> 36 <!-- hashKeySerializer、hashValueSerializer:对应的是Redis中的Hash类型 --> 37 <property name="keySerializer"> 38 <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean> 39 </property> 40 <property name="valueSerializer"> 41 <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean> 42 </property> 43 </bean> 44 45 </beans>
测试代码,如下所示:
关闭 linux 防火墙,或者在防火墙中开启 6379 端口。
1 import org.junit.Test; 2 import org.junit.runner.RunWith; 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.data.redis.core.RedisTemplate; 5 import org.springframework.test.context.ContextConfiguration; 6 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 8 /** 9 * @ProjectName: springredis 10 * @Package: PACKAGE_NAME 11 * @ClassName: RedisTest 12 * @Author: biehl 13 * @Description: ${description} 14 * @Date: 2020/5/24 10:16 15 * @Version: 1.0 16 */ 17 @RunWith(SpringJUnit4ClassRunner.class) 18 @ContextConfiguration("classpath:applicationContext.xml") 19 public class RedisTest { 20 21 @Autowired 22 private RedisTemplate<String, Object> redisTemplate; 23 24 /** 25 * 添加键值对 26 */ 27 @Test 28 public void test1() { 29 this.redisTemplate.opsForValue().set("key", "哈哈哈,学好数理化,走遍天下都不怕"); 30 } 31 32 /** 33 * 获取redis中的数据 34 */ 35 @Test 36 public void test2() { 37 String str = (String) this.redisTemplate.opsForValue().get("key"); 38 System.out.println(str); 39 } 40 41 42 }
Spring Data Redisd 存储实体对象。
1 import com.bie.po.Users; 2 import org.junit.Test; 3 import org.junit.runner.RunWith; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.data.redis.core.RedisTemplate; 6 import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; 7 import org.springframework.test.context.ContextConfiguration; 8 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 9 10 /** 11 * @ProjectName: springredis 12 * @Package: PACKAGE_NAME 13 * @ClassName: RedisTest 14 * @Author: biehl 15 * @Description: ${description} 16 * @Date: 2020/5/24 10:16 17 * @Version: 1.0 18 */ 19 @RunWith(SpringJUnit4ClassRunner.class) 20 @ContextConfiguration("classpath:applicationContext.xml") 21 public class RedisTest { 22 23 @Autowired 24 private RedisTemplate<String, Object> redisTemplate; 25 26 /** 27 * 添加Users 28 */ 29 @Test 30 public void test3() { 31 // 注意:实体类要实现序列化处理的,不然报异常。 32 Users users = new Users(1, "张三三", 25); 33 //更换序列化器 34 this.redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); 35 this.redisTemplate.opsForValue().set("users", users); 36 } 37 38 /** 39 * 获取Users 40 */ 41 @Test 42 public void test4() { 43 //更换序列化器 44 this.redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); 45 Users users = (Users) this.redisTemplate.opsForValue().get("users"); 46 System.out.println(users); 47 } 48 49 }
Spring Data Redis 以 JSON 的格式存储实体对象。
1 <!-- jackson的依赖包 --> 2 <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> 3 <dependency> 4 <groupId>com.fasterxml.jackson.core</groupId> 5 <artifactId>jackson-databind</artifactId> 6 <version>2.8.10</version> 7 </dependency> 8 <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> 9 <dependency> 10 <groupId>com.fasterxml.jackson.core</groupId> 11 <artifactId>jackson-core</artifactId> 12 <version>2.8.10</version> 13 </dependency> 14 <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> 15 <dependency> 16 <groupId>com.fasterxml.jackson.core</groupId> 17 <artifactId>jackson-annotations</artifactId> 18 <version>2.8.10</version> 19 </dependency>
测试代码,如所示:
1 import com.bie.po.Users; 2 import org.junit.Test; 3 import org.junit.runner.RunWith; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.data.redis.core.RedisTemplate; 6 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 7 import org.springframework.test.context.ContextConfiguration; 8 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 9 10 /** 11 * @ProjectName: springredis 12 * @Package: PACKAGE_NAME 13 * @ClassName: RedisTest 14 * @Author: biehl 15 * @Description: ${description} 16 * @Date: 2020/5/24 10:16 17 * @Version: 1.0 18 */ 19 @RunWith(SpringJUnit4ClassRunner.class) 20 @ContextConfiguration("classpath:applicationContext.xml") 21 public class RedisTest { 22 23 @Autowired 24 private RedisTemplate<String, Object> redisTemplate; 25 26 /** 27 * 添加Users JSON格式 28 */ 29 @Test 30 public void test5() { 31 Users users = new Users(1,"李四四",25); 32 33 this.redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Users.class)); 34 this.redisTemplate.opsForValue().set("usersjson", users); 35 } 36 37 /** 38 * 获取Uesrs JSON格式 39 */ 40 @Test 41 public void test6() { 42 this.redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Users.class)); 43 Users users = (Users) this.redisTemplate.opsForValue().get("usersjson"); 44 System.out.println(users); 45 } 46 47 }
以上是关于Spring整合HibernateHibernate JPASpring Data JPASpring Data Redis的主要内容,如果未能解决你的问题,请参考以下文章