SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-001-使用Hibernate(@Inject、@EnableTransactionManagement、@Repository、PersistenceExceptionTranslationPostProcessor)

时间:2022-10-31 16:54:18

一、结构

SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-001-使用Hibernate(@Inject、@EnableTransactionManagement、@Repository、PersistenceExceptionTranslationPostProcessor)

二、Repository层

1.

 1 package spittr.db;
2
3 import java.util.List;
4
5 import spittr.domain.Spitter;
6
7 /**
8 * Repository interface with operations for {@link Spitter} persistence.
9 * @author habuma
10 */
11 public interface SpitterRepository {
12
13 long count();
14
15 Spitter save(Spitter spitter);
16
17 Spitter findOne(long id);
18
19 Spitter findByUsername(String username);
20
21 List<Spitter> findAll();
22
23 }

 

2.

 1 package spittr.db;
2
3 import java.util.List;
4
5 import spittr.domain.Spittle;
6
7 /**
8 * Repository interface with operations for {@link Spittle} persistence.
9 * @author habuma
10 */
11 public interface SpittleRepository {
12
13 long count();
14
15 List<Spittle> findRecent();
16
17 List<Spittle> findRecent(int count);
18
19 Spittle findOne(long id);
20
21 Spittle save(Spittle spittle);
22
23 List<Spittle> findBySpitterId(long spitterId);
24
25 void delete(long id);
26
27 }

 

3.以前是用HibernateTemplate,但现在的最佳实践是用Hibernate contextual sessions and not use HibernateTemplate at all. This can be done by wiring a Hibernate SessionFactory directly into your repository and using it to obtain a session

@Repository有两作用:

(1)scanned by Spring component-scanning

(2)catch platformspecific exceptions and rethrow them as one of Spring’s unified unchecked exceptions

But if you’re using Hibernate contextual sessions and not a Hibernate template,how can the exception translation take place?要实现第2个作用还要配在配置文件配置PersistenceExceptionTranslationPostProcessor,如:

 

1 @Bean
2 public BeanPostProcessor persistenceTranslation() {
3 return new PersistenceExceptionTranslationPostProcessor();
4 }

 

 

 

 1 package spittr.db.hibernate4;
2
3 import java.io.Serializable;
4 import java.util.List;
5
6 import javax.inject.Inject;
7
8 import org.hibernate.Session;
9 import org.hibernate.SessionFactory;
10 import org.hibernate.criterion.Restrictions;
11 import org.springframework.stereotype.Repository;
12
13 import spittr.db.SpitterRepository;
14 import spittr.domain.Spitter;
15
16 @Repository
17 public class HibernateSpitterRepository implements SpitterRepository {
18
19 private SessionFactory sessionFactory;
20
21 @Inject
22 public HibernateSpitterRepository(SessionFactory sessionFactory) {
23 this.sessionFactory = sessionFactory; //<co id="co_InjectSessionFactory"/>
24 }
25
26 private Session currentSession() {
27 return sessionFactory.getCurrentSession();//<co id="co_RetrieveCurrentSession"/>
28 }
29
30 public long count() {
31 return findAll().size();
32 }
33
34 public Spitter save(Spitter spitter) {
35 Serializable id = currentSession().save(spitter); //<co id="co_UseCurrentSession"/>
36 return new Spitter((Long) id,
37 spitter.getUsername(),
38 spitter.getPassword(),
39 spitter.getFullName(),
40 spitter.getEmail(),
41 spitter.isUpdateByEmail());
42 }
43
44 public Spitter findOne(long id) {
45 return (Spitter) currentSession().get(Spitter.class, id);
46 }
47
48 public Spitter findByUsername(String username) {
49 return (Spitter) currentSession()
50 .createCriteria(Spitter.class)
51 .add(Restrictions.eq("username", username))
52 .list().get(0);
53 }
54
55 public List<Spitter> findAll() {
56 return (List<Spitter>) currentSession()
57 .createCriteria(Spitter.class).list();
58 }
59
60 }

 

4.

 1 package spittr.db.hibernate4;
2
3 import java.io.Serializable;
4 import java.util.List;
5
6 import javax.inject.Inject;
7
8 import org.hibernate.Criteria;
9 import org.hibernate.Session;
10 import org.hibernate.SessionFactory;
11 import org.hibernate.criterion.Order;
12 import org.hibernate.criterion.Restrictions;
13 import org.springframework.stereotype.Repository;
14
15 import spittr.db.SpittleRepository;
16 import spittr.domain.Spittle;
17
18 @Repository
19 public class HibernateSpittleRepository implements SpittleRepository {
20
21 private SessionFactory sessionFactory;
22
23 @Inject
24 public HibernateSpittleRepository(SessionFactory sessionFactory) {
25 this.sessionFactory = sessionFactory;
26 }
27
28 private Session currentSession() {
29 return sessionFactory.getCurrentSession();//<co id="co_RetrieveCurrentSession"/>
30 }
31
32 public long count() {
33 return findAll().size();
34 }
35
36 public List<Spittle> findRecent() {
37 return findRecent(10);
38 }
39
40 public List<Spittle> findRecent(int count) {
41 return (List<Spittle>) spittleCriteria()
42 .setMaxResults(count)
43 .list();
44 }
45
46 public Spittle findOne(long id) {
47 return (Spittle) currentSession().get(Spittle.class, id);
48 }
49
50 public Spittle save(Spittle spittle) {
51 Serializable id = currentSession().save(spittle);
52 return new Spittle(
53 (Long) id,
54 spittle.getSpitter(),
55 spittle.getMessage(),
56 spittle.getPostedTime());
57 }
58
59 public List<Spittle> findBySpitterId(long spitterId) {
60 return spittleCriteria()
61 .add(Restrictions.eq("spitter.id", spitterId))
62 .list();
63 }
64
65 public void delete(long id) {
66 currentSession().delete(findOne(id));
67 }
68
69 public List<Spittle> findAll() {
70 return (List<Spittle>) spittleCriteria().list();
71 }
72
73 private Criteria spittleCriteria() {
74 return currentSession()
75 .createCriteria(Spittle.class)
76 .addOrder(Order.desc("postedTime"));
77 }
78
79 }

 

三、Domainn层

1.

 1 package spittr.domain;
2
3 import javax.persistence.Column;
4 import javax.persistence.Entity;
5 import javax.persistence.GeneratedValue;
6 import javax.persistence.GenerationType;
7 import javax.persistence.Id;
8
9
10 @Entity
11 public class Spitter {
12
13 private Spitter() {}
14
15 @Id
16 @GeneratedValue(strategy=GenerationType.IDENTITY)
17 private Long id;
18
19 @Column(name="username")
20 private String username;
21
22 @Column(name="password")
23 private String password;
24
25 @Column(name="fullname")
26 private String fullName;
27
28 @Column(name="email")
29 private String email;
30
31 @Column(name="updateByEmail")
32 private boolean updateByEmail;
33
34 public Spitter(Long id, String username, String password, String fullName,
35 String email, boolean updateByEmail) {
36 this.id = id;
37 this.username = username;
38 this.password = password;
39 this.fullName = fullName;
40 this.email = email;
41 this.updateByEmail = updateByEmail;
42 }
43
44 public Long getId() {
45 return id;
46 }
47
48 public String getUsername() {
49 return username;
50 }
51
52 public String getPassword() {
53 return password;
54 }
55
56 public String getFullName() {
57 return fullName;
58 }
59
60 public String getEmail() {
61 return email;
62 }
63
64 public boolean isUpdateByEmail() {
65 return updateByEmail;
66 }
67
68 }

 

2.

 1 package spittr.domain;
2
3 import java.util.Date;
4
5 import javax.persistence.Column;
6 import javax.persistence.Entity;
7 import javax.persistence.GeneratedValue;
8 import javax.persistence.GenerationType;
9 import javax.persistence.Id;
10 import javax.persistence.JoinColumn;
11 import javax.persistence.ManyToOne;
12
13 @Entity
14 public class Spittle {
15
16 private Spittle() {}
17
18 @Id
19 @GeneratedValue(strategy=GenerationType.IDENTITY)
20 private Long id;
21
22 @ManyToOne
23 @JoinColumn(name="spitter")
24 private Spitter spitter;
25
26 @Column
27 private String message;
28
29 @Column
30 private Date postedTime;
31
32 public Spittle(Long id, Spitter spitter, String message, Date postedTime) {
33 this.id = id;
34 this.spitter = spitter;
35 this.message = message;
36 this.postedTime = postedTime;
37 }
38
39 public Long getId() {
40 return this.id;
41 }
42
43 public String getMessage() {
44 return this.message;
45 }
46
47 public Date getPostedTime() {
48 return this.postedTime;
49 }
50
51 public Spitter getSpitter() {
52 return this.spitter;
53 }
54
55 }

 

 

四、配置文件及数据库文件

0.

 1 package spittr.db.hibernate4;
2
3 import java.io.IOException;
4 import java.util.Properties;
5
6 import javax.inject.Inject;
7 import javax.sql.DataSource;
8
9 import org.hibernate.SessionFactory;
10 import org.springframework.context.annotation.Bean;
11 import org.springframework.context.annotation.ComponentScan;
12 import org.springframework.context.annotation.Configuration;
13 import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
14 import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
15 import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
16 //import org.springframework.orm.hibernate4.HibernateTransactionManager;
17 //import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
18 import org.springframework.orm.hibernate5.HibernateTransactionManager;
19 import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
20 import org.springframework.transaction.PlatformTransactionManager;
21 import org.springframework.transaction.annotation.EnableTransactionManagement;
22 import org.springframework.transaction.annotation.TransactionManagementConfigurer;
23
24 @Configuration
25 @EnableTransactionManagement
26 @ComponentScan
27 public class RepositoryTestConfig implements TransactionManagementConfigurer {
28
29 @Inject
30 private SessionFactory sessionFactory;
31
32 @Bean
33 public DataSource dataSource() {
34 EmbeddedDatabaseBuilder edb = new EmbeddedDatabaseBuilder();
35 edb.setType(EmbeddedDatabaseType.H2);
36 edb.addScript("spittr/db/hibernate4/schema.sql");
37 edb.addScript("spittr/db/hibernate4/test-data.sql");
38 EmbeddedDatabase embeddedDatabase = edb.build();
39 return embeddedDatabase;
40 }
41
42 //@Bean
43 public PlatformTransactionManager annotationDrivenTransactionManager() {
44 System.out.println(sessionFactory);
45 HibernateTransactionManager transactionManager = new HibernateTransactionManager();
46 transactionManager.setSessionFactory(sessionFactory);
47 return transactionManager;
48 }
49
50 @Bean
51 public SessionFactory sessionFactoryBean() {
52 try {
53 LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
54 lsfb.setDataSource(dataSource());
55 lsfb.setPackagesToScan("spittr.domain");
56 Properties props = new Properties();
57 props.setProperty("dialect", "org.hibernate.dialect.H2Dialect");
58 lsfb.setHibernateProperties(props);
59 lsfb.afterPropertiesSet();
60 SessionFactory object = lsfb.getObject();
61 return object;
62 } catch (IOException e) {
63 return null;
64 }
65 }
66 }

 

1.

1 log4j.rootCategory=INFO, stdout
2
3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
5 log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %40.40c:%4L - %m%n

 

2.RepositoryTest-context.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" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
4 xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context"
5 xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
8
9
10 <context:component-scan base-package="spittr.db.hibernate4" />
11
12 <bean id="transactionManager"
13 class="org.springframework.orm.hibernate4.HibernateTransactionManager"
14 c:_-ref="sessionFactory" />
15
16 <jdbc:embedded-database id="dataSource" type="H2">
17 <jdbc:script location="spittr/db/hibernate4/schema.sql" />
18 <jdbc:script location="spittr/db/hibernate4/test-data.sql" />
19 </jdbc:embedded-database>
20
21 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
22 <property name="dataSource" ref="dataSource"/>
23 <property name="packagesToScan" value="com.habuma.spitter.domain" />
24 <property name="hibernateProperties">
25 <props>
26 <prop key="dialect">org.hibernate.dialect.H2Dialect</prop>
27 </props>
28 </property>
29 </bean>
30
31 <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
32
33 </beans>

 

3.schema.sql

 1 drop table if exists spittle;
2 drop table if exists spitter;
3
4 create table spitter (
5 id identity,
6 username varchar(25) not null,
7 password varchar(25) not null,
8 fullName varchar(100) not null,
9 email varchar(50) not null,
10 updateByEmail boolean not null
11 );
12
13 create table spittle (
14 id integer identity primary key,
15 spitter integer not null,
16 message varchar(2000) not null,
17 postedTime datetime not null,
18 foreign key (spitter) references spitter(id)
19 );

 

4.test-data.sql

 1 insert into Spitter (username, password, fullname, email, updateByEmail) values ('habuma', 'password', 'Craig Walls', 'craig@habuma.com', false);
2 insert into Spitter (username, password, fullname, email, updateByEmail) values ('mwalls', 'password', 'Michael Walls', 'mwalls@habuma.com', true);
3 insert into Spitter (username, password, fullname, email, updateByEmail) values ('chuck', 'password', 'Chuck Wagon', 'chuck@habuma.com', false);
4 insert into Spitter (username, password, fullname, email, updateByEmail) values ('artnames', 'password', 'Art Names', 'art@habuma.com', true);
5
6 insert into Spittle (spitter, message, postedTime) values (1, 'This is a test spittle message', '2012-06-09 22:00:00Z');
7 insert into Spittle (spitter, message, postedTime) values (1, 'This is another test spittle message', '2012-06-09 22:10:00Z');
8 insert into Spittle (spitter, message, postedTime) values (1, 'This is a third test spittle message', '2012-07-04 23:30:00Z');
9 insert into Spittle (spitter, message, postedTime) values (2, 'Hello from Chuck!', '2012-03-25 12:15:00Z');
10 insert into Spittle (spitter, message, postedTime) values (4, 'Hello from Art!', '2012-03-25 12:15:00Z');
11 insert into Spittle (spitter, message, postedTime) values (4, 'Hello again from Art!', '2012-03-25 12:25:00Z');
12 insert into Spittle (spitter, message, postedTime) values (4, 'Hola from Arthur!', '2012-03-25 12:35:00Z');
13 insert into Spittle (spitter, message, postedTime) values (4, 'Buenos Dias from Art!', '2012-03-25 12:45:00Z');
14 insert into Spittle (spitter, message, postedTime) values (4, 'Ni Hao from Art!', '2012-03-25 12:55:00Z');
15 insert into Spittle (spitter, message, postedTime) values (4, 'Guten Tag from Art!', '2012-03-25 13:05:00Z');
16 insert into Spittle (spitter, message, postedTime) values (4, 'Konnichi wa from Art!', '2012-03-25 13:15:00Z');
17 insert into Spittle (spitter, message, postedTime) values (4, 'Buon giorno from Art!', '2012-03-25 13:25:00Z');
18 insert into Spittle (spitter, message, postedTime) values (4, 'Bonjour from Art!', '2012-03-25 13:35:00Z');
19 insert into Spittle (spitter, message, postedTime) values (4, 'Aloha from Art!', '2012-03-25 13:45:00Z');
20 insert into Spittle (spitter, message, postedTime) values (4, 'God dag from Art!', '2012-03-25 13:55:00Z');

 

五、测试文件

1.

  1 package spittr.db.hibernate4;
2
3 import static org.junit.Assert.*;
4
5 import java.util.List;
6
7 import org.junit.BeforeClass;
8 import org.junit.Test;
9 import org.junit.runner.RunWith;
10 import org.springframework.beans.factory.annotation.Autowired;
11 import org.springframework.test.context.ContextConfiguration;
12 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13 import org.springframework.transaction.annotation.Transactional;
14
15 import spittr.db.SpitterRepository;
16 import spittr.domain.Spitter;
17
18 @RunWith(SpringJUnit4ClassRunner.class)
19 @ContextConfiguration(classes = RepositoryTestConfig.class)
20 public class SpitterRepositoryTest {
21
22 @Autowired
23 SpitterRepository spitterRepository;
24
25 @Test
26 @Transactional
27 public void count() {
28 assertEquals(4, spitterRepository.count());
29 }
30
31 @Test
32 @Transactional
33 public void findAll() {
34 List<Spitter> spitters = spitterRepository.findAll();
35 assertEquals(4, spitters.size());
36 assertSpitter(0, spitters.get(0));
37 assertSpitter(1, spitters.get(1));
38 assertSpitter(2, spitters.get(2));
39 assertSpitter(3, spitters.get(3));
40 }
41
42 @Test
43 @Transactional
44 public void findByUsername() {
45 assertSpitter(0, spitterRepository.findByUsername("habuma"));
46 assertSpitter(1, spitterRepository.findByUsername("mwalls"));
47 assertSpitter(2, spitterRepository.findByUsername("chuck"));
48 assertSpitter(3, spitterRepository.findByUsername("artnames"));
49 }
50
51 @Test
52 @Transactional
53 public void findOne() {
54 assertSpitter(0, spitterRepository.findOne(1L));
55 assertSpitter(1, spitterRepository.findOne(2L));
56 assertSpitter(2, spitterRepository.findOne(3L));
57 assertSpitter(3, spitterRepository.findOne(4L));
58 }
59
60 @Test
61 @Transactional
62 public void save_newSpitter() {
63 assertEquals(4, spitterRepository.count());
64 Spitter spitter = new Spitter(null, "newbee", "letmein", "New Bee",
65 "newbee@habuma.com", true);
66 Spitter saved = spitterRepository.save(spitter);
67 assertEquals(5, spitterRepository.count());
68 assertSpitter(4, saved);
69 assertSpitter(4, spitterRepository.findOne(5L));
70 }
71
72 private static void assertSpitter(int expectedSpitterIndex, Spitter actual) {
73 assertSpitter(expectedSpitterIndex, actual, "Newbie");
74 }
75
76 private static void assertSpitter(int expectedSpitterIndex, Spitter actual,
77 String expectedStatus) {
78 Spitter expected = SPITTERS[expectedSpitterIndex];
79 assertEquals(expected.getId(), actual.getId());
80 assertEquals(expected.getUsername(), actual.getUsername());
81 assertEquals(expected.getPassword(), actual.getPassword());
82 assertEquals(expected.getFullName(), actual.getFullName());
83 assertEquals(expected.getEmail(), actual.getEmail());
84 assertEquals(expected.isUpdateByEmail(), actual.isUpdateByEmail());
85 }
86
87 private static Spitter[] SPITTERS = new Spitter[6];
88
89 @BeforeClass
90 public static void before() {
91 SPITTERS[0] = new Spitter(1L, "habuma", "password", "Craig Walls",
92 "craig@habuma.com", false);
93 SPITTERS[1] = new Spitter(2L, "mwalls", "password", "Michael Walls",
94 "mwalls@habuma.com", true);
95 SPITTERS[2] = new Spitter(3L, "chuck", "password", "Chuck Wagon",
96 "chuck@habuma.com", false);
97 SPITTERS[3] = new Spitter(4L, "artnames", "password", "Art Names",
98 "art@habuma.com", true);
99 SPITTERS[4] = new Spitter(5L, "newbee", "letmein", "New Bee",
100 "newbee@habuma.com", true);
101 SPITTERS[5] = new Spitter(4L, "arthur", "letmein", "Arthur Names",
102 "arthur@habuma.com", false);
103 }
104
105 }

 

2.

  1 package spittr.db.hibernate4;
2
3 import static org.junit.Assert.*;
4
5 import java.util.Date;
6 import java.util.List;
7
8 import org.junit.Test;
9 import org.junit.runner.RunWith;
10 import org.springframework.beans.factory.annotation.Autowired;
11 import org.springframework.test.context.ContextConfiguration;
12 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
13 import org.springframework.transaction.annotation.Transactional;
14
15 import spittr.db.SpittleRepository;
16 import spittr.domain.Spitter;
17 import spittr.domain.Spittle;
18
19 @RunWith(SpringJUnit4ClassRunner.class)
20 @ContextConfiguration(classes=RepositoryTestConfig.class)
21 public class SpittleRepositoryTest {
22
23 @Autowired
24 SpittleRepository spittleRepository;
25
26 @Test
27 @Transactional
28 public void count() {
29 assertEquals(15, spittleRepository.count());
30 }
31
32 @Test
33 @Transactional
34 public void findRecent() {
35 // default case
36 {
37 List<Spittle> recent = spittleRepository.findRecent();
38 assertRecent(recent, 10);
39 }
40
41 // specific count case
42 {
43 List<Spittle> recent = spittleRepository.findRecent(5);
44 assertRecent(recent, 5);
45 }
46 }
47
48 @Test
49 @Transactional
50 public void findOne() {
51 Spittle thirteen = spittleRepository.findOne(13);
52 assertEquals(13, thirteen.getId().longValue());
53 assertEquals("Bonjour from Art!", thirteen.getMessage());
54 assertEquals(1332682500000L, thirteen.getPostedTime().getTime());
55 assertEquals(4, thirteen.getSpitter().getId().longValue());
56 assertEquals("artnames", thirteen.getSpitter().getUsername());
57 assertEquals("password", thirteen.getSpitter().getPassword());
58 assertEquals("Art Names", thirteen.getSpitter().getFullName());
59 assertEquals("art@habuma.com", thirteen.getSpitter().getEmail());
60 assertTrue(thirteen.getSpitter().isUpdateByEmail());
61 }
62
63 @Test
64 @Transactional
65 public void findBySpitter() {
66 List<Spittle> spittles = spittleRepository.findBySpitterId(4L);
67 assertEquals(11, spittles.size());
68 for (int i = 0; i < 11; i++) {
69 assertEquals(15-i, spittles.get(i).getId().longValue());
70 }
71 }
72
73 @Test
74 @Transactional
75 public void save() {
76 assertEquals(15, spittleRepository.count());
77 Spitter spitter = spittleRepository.findOne(13).getSpitter();
78 Spittle spittle = new Spittle(null, spitter, "Un Nuevo Spittle from Art", new Date());
79 Spittle saved = spittleRepository.save(spittle);
80 assertEquals(16, spittleRepository.count());
81 assertNewSpittle(saved);
82 assertNewSpittle(spittleRepository.findOne(16L));
83 }
84
85 @Test
86 @Transactional
87 public void delete() {
88 assertEquals(15, spittleRepository.count());
89 assertNotNull(spittleRepository.findOne(13));
90 spittleRepository.delete(13L);
91 assertEquals(14, spittleRepository.count());
92 assertNull(spittleRepository.findOne(13));
93 }
94
95 private void assertRecent(List<Spittle> recent, int count) {
96 long[] recentIds = new long[] {3,2,1,15,14,13,12,11,10,9};
97 assertEquals(count, recent.size());
98 for (int i = 0; i < count; i++) {
99 assertEquals(recentIds[i], recent.get(i).getId().longValue());
100 }
101 }
102
103 private void assertNewSpittle(Spittle spittle) {
104 assertEquals(16, spittle.getId().longValue());
105 }
106
107 }