Spring整合Hibernate、Hibernate JPA、Spring Data JPA、Spring 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 "1.0" encoding="UTF-8"?>
  2 "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     4.0.0
  7 
  8     com.bie
  9     spring-hibernate
 10     1.0-SNAPSHOT
 11 
 12     
 13         
 14         
 15         
 16             org.springframework
 17             spring-context
 18             4.2.0.RELEASE
 19         
 20         
 21         
 22             org.springframework
 23             spring-core
 24             4.2.0.RELEASE
 25         
 26         
 27         
 28             org.springframework
 29             spring-beans
 30             4.2.0.RELEASE
 31         
 32 
 33         
 34         
 35         
 36             org.springframework
 37             spring-aop
 38             4.2.0.RELEASE
 39         
 40         
 41         
 42             org.springframework
 43             spring-aspects
 44             4.2.0.RELEASE
 45         
 46         
 47         
 48             org.aspectj
 49             aspectjrt
 50             1.9.2
 51         
 52 
 53         
 54         
 55         
 56             org.springframework
 57             spring-jdbc
 58             4.2.0.RELEASE
 59         
 60         
 61         
 62             org.springframework
 63             spring-tx
 64             4.2.0.RELEASE
 65         
 66 
 67         
 68         
 69         
 70             org.springframework
 71             spring-orm
 72             4.2.0.RELEASE
 73         
 74         
 75         
 76         
 77             org.springframework
 78             spring-test
 79             4.2.0.RELEASE
 80             test
 81         
 82 
 83         
 84         
 85         
 86             commons-logging
 87             commons-logging
 88             1.1.1
 89         
 90 
 91         
 92         
 93         
 94             org.hibernate
 95             hibernate-core
 96             5.0.7.Final
 97         
 98 
 99         
100         
101         
102             mysql
103             mysql-connector-java
104             5.1.6
105         
106 
107         
108         
109         
110             com.mchange
111             c3p0
112             0.9.5.2
113         
114         
115         
116             org.hibernate
117             hibernate-c3p0
118             5.0.7.Final
119         
120 
121         
122         
123         
124             org.hibernate
125             hibernate-entitymanager
126             5.0.7.Final
127         
128 
129         
130         
131         
132             junit
133             junit
134             4.12
135             test
136         
137 
138 
139     
140 
141 

在配置文件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 "1.0" encoding="UTF-8"?>
 2 "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     
14     "classpath:jdbc.properties"/>
15 
16     
17     "dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
18         "jdbcUrl" value="${jdbc.url}"/>
19         "driverClass" value="${jdbc.driver.class}"/>
20         "user" value="${jdbc.username}"/>
21         "password" value="${jdbc.password}"/>
22     
23 
24     
25     
26     
27     "sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
28         
29         "dataSource" ref="dataSource"/>
30         
31         "hibernateProperties">
32             
33                 
34                 "hibernate.show_sql">true
35                 
36                 "hibernate.hbm2ddl.auto">update
37             
38         
39         
40         "packagesToScan">
41             
42                 
43                 com.bie.po
44             
45         
46     
47 
48     
49     "transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
50         
51         "sessionFactory" ref="sessionFactory"/>
52     
53 
54     
55     "transactionManager"/>
56 
57     
58     base-package="com.bie"/>
59 
60     
61     "hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
62         
63         "sessionFactory" ref="sessionFactory"/>
64     
65 
66 

创建实体类,如下所示:

 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 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 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 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 selectUserByName(String username);
48 
49     /**
50      * 根据sql语句进行名称的查询。
51      *
52      * @param username
53      * @return
54      */
55     List 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 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 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 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 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 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 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 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 
2 
3 
4     org.hibernate
5     hibernate-entitymanager
6     5.0.7.Final
7 

修改spring的配置文件applicationContext.xml。

 1 "1.0" encoding="UTF-8"?>
 2 "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     
14     "classpath:jdbc.properties"/>
15 
16     
17     "dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
18         "jdbcUrl" value="${jdbc.url}"/>
19         "driverClass" value="${jdbc.driver.class}"/>
20         "user" value="${jdbc.username}"/>
21         "password" value="${jdbc.password}"/>
22     
23 
24     
25     
26     "entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
27         
28         "dataSource" ref="dataSource"/>
29         
30         "jpaVendorAdapter">
31             class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
32                  
33                 "database" value="MYSQL"/>
34                 
35                 "generateDdl" value="true"/>
36                 
37                 "showSql" value="true"/>
38             
39          
40         "packagesToScan">
41             
42                 com.bie.po
43             
44         
45     
46 
47     
48     "transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
49         "entityManagerFactory" ref="entityManagerFactory"/>
50     
51 
52 
53 
54     
55     "transactionManager"/>
56 
57     
58     base-package="com.bie"/>
59 
60 
61 

创建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 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 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 selectUserByNameUseCriteria(String username) {
81         // CriteriaBuilder 对象:创建一个 CriteriaQuery,创建查询条件。
82         CriteriaBuilder builber = this.entityManager.getCriteriaBuilder();
83         // CriteriaQuery 对象:执行查询的 Criteria 对象
84         // select * from tb_users
85         CriteriaQuery query = builber.createQuery(Users.class);
86         // 获取要查询的实体类的对象
87         Root 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 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 
 2 
 3 
 4     org.springframework.data
 5     spring-data-jpa
 6     1.9.0.RELEASE
 7 
 8 
 9 
10     org.slf4j
11     slf4j-log4j12
12     1.7.2
13     test
14 

修改spring的配置文件applicationContext.xml。

 1 "1.0" encoding="UTF-8"?>
 2 "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     
17     "classpath:jdbc.properties"/>
18 
19     
20     "dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
21         "jdbcUrl" value="${jdbc.url}"/>
22         "driverClass" value="${jdbc.driver.class}"/>
23         "user" value="${jdbc.username}"/>
24         "password" value="${jdbc.password}"/>
25     
26 
27     
28     
29     "entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
30         
31         "dataSource" ref="dataSource"/>
32         
33         "jpaVendorAdapter">
34             class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
35                  
36                 "database" value="MYSQL"/>
37                 
38                 "generateDdl" value="true"/>
39                 
40                 "showSql" value="true"/>
41             
42         
43         
44         "packagesToScan">
45             
46                 com.bie.po
47             
48         
49     
50 
51     
52     "transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
53         "entityManagerFactory" ref="entityManagerFactory"/>
54     
55 
56     
57     "transactionManager"/>
58 
59     
60     base-package="com.bie"/>
61 
62 
63     
64     
65     base-package="com.bie.dao"/>
66 
67 

创建dao层的接口,继承JpaRepository,JpaRepository泛型参数一是实体类的名称,参数二是实体类的主键类型。

 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  * 

9 * JpaRepository泛型参数一是实体类的名称,参数二是实体类的主键类型。 10 */ 11 public interface UserDao extends JpaRepository { 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 {
 9 
10     /**
11      * @param string
12      * @return
13      */
14     List findByNameIs(String string);
15 
16     /**
17      * @param string
18      * @return
19      */
20     List findByNameLike(String string);
21 
22     /**
23      * @param name
24      * @param age
25      * @return
26      */
27     List 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 list = this.userDao.findByNameIs("张飒飒");
31         for (Users users : list) {
32             System.out.println(users);
33         }
34     }
35 
36     /**
37      * 需求:根据用户姓名做 Like 处理
38      * 

39 * Like:条件关键字 40 */ 41 @Test 42 public void test2() { 43 List 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 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 {
10 
11     //使用@Query 注解查询
12     @Query(value = "from Users where name = ?")
13     List queryUserByNameUseJPQL(String name);
14 
15     @Query("from Users where name like ?")
16     List queryUserByLikeNameUseJPQL(String name);
17 
18     @Query("from Users where name = ? and age >= ?")
19     List 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 {
10 
11     // 使用@Query注解查询SQL
12     // nativeQuery:默认的是false,表示不开启sql查询,是否对value中的语句做转义。
13     @Query(value = "select * from tb_users where userName = ?", nativeQuery = true)
14     List queryUserByNameUseSQL(String name);
15 
16     @Query(value = "select * from tb_users where userName like ?", nativeQuery = true)
17     List queryUserByLikeNameUseSQL(String name);
18 
19     @Query(value = "select * from tb_users where userName = ? and userAge >= ?", nativeQuery = true)
20     List 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 {
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 {
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 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 list = (List) 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 {
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 p = this.userDao.findAll(pageable);
38         System.out.println("数据的总条数:" + p.getTotalElements());
39         System.out.println("总页数:" + p.getTotalPages());
40         List 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 list = (List) 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 list = (List) 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 {
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 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:不能单独使用,需要配合着 jpa 中的其他接口一起使用
10  */
11 public interface UserDao extends JpaRepository, JpaSpecificationExecutor {
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 specification = new Specification() {
 40             /**
 41              *
 42              * @param root 根对象。封装了查询条件的对象
 43              * @param query 定义了一个基本的查询.一般不使用
 44              * @param cb 创建一个查询条件
 45              * @return Predicate:定义了查询条件
 46              */
 47             @Override
 48             public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
 49                 Predicate pre = cb.equal(root.get("name"), "王五五");
 50                 return pre;
 51             }
 52 
 53         };
 54         List 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 specification = new Specification() {
 67 
 68             @Override
 69             public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
 70                 List 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 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 specification = new Specification() {
 92 
 93             @Override
 94             public Predicate toPredicate(Root 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 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 specification = new Specification() {
112 
113             @Override
114             public Predicate toPredicate(Root 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 page = this.userDao.findAll(specification, pageable);
123         System.out.println("总条数:" + page.getTotalElements());
124         System.out.println("总页数:" + page.getTotalPages());
125         List 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 specification = new Specification() {
138 
139             @Override
140             public Predicate toPredicate(Root 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 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 specification = new Specification() {
165 
166             @Override
167             public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
168                 return cb.like(root.get("name").as(String.class), "王%");
169             }
170 
171         };
172         Page page = this.userDao.findAll(specification, pageable);
173         System.out.println("总条数:" + page.getTotalElements());
174         System.out.println("总页数:" + page.getTotalPages());
175         List 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, JpaSpecificationExecutor, 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来生成构造器、setter\getter等等方法
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 usersSet = new HashSet();
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 getUsersSet() {
57         return usersSet;
58     }
59 
60     public void setUsersSet(Set 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 {
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 = 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 getMenus() {
58         return menus;
59     }
60 
61     public void setMenus(Set 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 = 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 getRoles() {
82         return roles;
83     }
84 
85     public void setRoles(Set 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 = roles.getMenus();
56         for (Menus menus2 : menus) {
57             System.out.println("菜单信息:" + menus2);
58         }
59     }
60 
61 }

 

4、Spring Data Redis帮助我们更方便,更容易操作Redis。

  1 "1.0" encoding="UTF-8"?>
  2 "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     4.0.0
  7 
  8     com.bie
  9     spring-redis
 10     1.0-SNAPSHOT
 11 
 12     
 13         
 14         
 15         
 16             org.springframework
 17             spring-context
 18             4.2.0.RELEASE
 19         
 20         
 21         
 22             org.springframework
 23             spring-core
 24             4.2.0.RELEASE
 25         
 26         
 27         
 28             org.springframework
 29             spring-beans
 30             4.2.0.RELEASE
 31         
 32 
 33         
 34         
 35         
 36             org.springframework
 37             spring-aop
 38             4.2.0.RELEASE
 39         
 40         
 41         
 42             org.springframework
 43             spring-aspects
 44             4.2.0.RELEASE
 45         
 46         
 47         
 48             org.aspectj
 49             aspectjrt
 50             1.9.2
 51         
 52 
 53         
 54         
 55         
 56             org.springframework
 57             spring-jdbc
 58             4.2.0.RELEASE
 59         
 60         
 61         
 62             org.springframework
 63             spring-tx
 64             4.2.0.RELEASE
 65         
 66 
 67         
 68         
 69         
 70             commons-logging
 71             commons-logging
 72             1.1.1
 73         
 74 
 75         
 76         
 77         
 78             org.springframework
 79             spring-test
 80             4.2.0.RELEASE
 81             test
 82         
 83 
 84         
 85         
 86         
 87             junit
 88             junit
 89             4.12
 90             test
 91         
 92 
 93         
 94         
 95         
 96             org.springframework.data
 97             spring-data-redis
 98             1.6.0.RELEASE
 99         
100         
101         
102             redis.clients
103             jedis
104             2.7.2
105         
106 
107 
108     
109 
110 

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 "1.0" encoding="UTF-8"?>
 2 "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     
11     "classpath:redis.properties"/>
12 
13     
14     "poolConfig" class="redis.clients.jedis.JedisPoolConfig">
15         "maxTotal" value="${redis.pool.maxtTotal}"/>
16         "maxIdle" value="${redis.pool.maxIdle}"/>
17         "minIdle" value="${redis.pool.minIdle}"/>
18     
19 
20     
21     "jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
22         
23         "hostName" value="${redis.hostname}"/>
24         
25         "port" value="${redis.port}"/>
26         
27         "poolConfig" ref="poolConfig"/>
28     
29 
30     
31     "redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
32         
33         "connectionFactory" ref="jedisConnectionFactory"/>
34         
35         
36         
37         "keySerializer">
38             class="org.springframework.data.redis.serializer.StringRedisSerializer">
39         
40         "valueSerializer">
41             class="org.springframework.data.redis.serializer.StringRedisSerializer">
42         
43     
44 
45 

测试代码,如下所示:

关闭 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 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 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 
 2 
 3 
 4     com.fasterxml.jackson.core
 5     jackson-databind
 6     2.8.10
 7 
 8 
 9 
10     com.fasterxml.jackson.core
11     jackson-core
12     2.8.10
13 
14 
15 
16     com.fasterxml.jackson.core
17     jackson-annotations
18     2.8.10
19 

测试代码,如所示:

 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 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整合Hibernate、Hibernate JPA、Spring Data JPA、Spring Data Redis)