אביב JPA - מאגרים מרובים

1. סקירה כללית

במדריך זה נבצע תצורת אביב פשוטה עבור a מערכת JPA של Spring Data עם מספר מאגרי מידע.

2. הישויות

ראשית - בואו ניצור שתי ישויות פשוטות - כל אחת מהן חיה במסד נתונים נפרד.

הנה הראשון “מִשׁתַמֵשׁישות:

חבילה com.baeldung.multipledb.model.user; @Entity @Table (schema = "משתמשים") משתמש בכיתה ציבורית {@Id @GeneratedValue (אסטרטגיה = GenerationType.AUTO) מזהה פרטי פרטי; שם מחרוזת פרטי; @Column (ייחודי = נכון, בטל = שקר) דוא"ל מחרוזת פרטי; גיל פרטי פרטי; }

והישות השנייה - “מוצר“:

חבילה com.baeldung.multipledb.model.product; @Entity @Table (schema = "products") מוצר ציבורי {@Id מזהה פרטי פרטי; שם מחרוזת פרטי; מחיר כפול פרטי; }

כפי שאתה יכול לראות, שתי הגופים ממוקמים גם בחבילות עצמאיות - זה יהיה חשוב כאשר אנו עוברים לתצורה.

3. מאגרי JPA

לאחר מכן - בואו נסתכל על שני המאגרים שלנו ב- JPA - UserRepository:

חבילה com.baeldung.multipledb.dao.user; ממשק ציבורי UserRepository מרחיב את JpaRepository {}

וגם מאגר מוצר:

חבילה com.baeldung.multipledb.dao.product; ממשק ציבורי ProductRepository מרחיב את JpaRepository {}

שים לב, שוב, כיצד יצרנו את שני המאגרים הללו בחבילות שונות.

4. הגדר JPA עם Java

הבא - בואו נגיע לתצורת האביב בפועל. נתחיל בהגדרת שני שיעורי תצורה - אחד עבור ה- מִשׁתַמֵשׁ והשני עבור מוצר.

בכל אחד משיעורי התצורה הללו, נצטרך להגדיר את הממשקים הבאים עבור מִשׁתַמֵשׁ:

  • מקור מידע
  • EntityManagerFactory (userEntityManager)
  • TransactionManager (userTransactionManager)

נתחיל בבדיקת תצורת המשתמש:

@Configuration @PropertySource ({"classpath: persistence-multiple-db.properties"}) @EnableJpaRepositories (basePackages = "com.baeldung.multipledb.dao.user", entityManagerFactoryRef = "userEntityManager", userManagerRefanagerRefan = מנהל "=" PersistenceUserConfiguration {@ Envy Private Environment Env; @Bean @Primary ציבור LocalContainerEntityManagerFactoryBean userEntityManager () {LocalContainerEntityManagerFactoryBean em = חדש LocalContainerEntityManagerFactoryBean (); em.setDataSource (userDataSource ()); em.setPackagesToScan (מחרוזת חדשה [] {"com.baeldung.multipledb.model.user"}); HibernateJpaVendorAdapter vendorAdapter = חדש HibernateJpaVendorAdapter (); em.setJpaVendorAdapter (vendorAdapter); מאפייני HashMap = HashMap חדש (); properties.put ("hibernate.hbm2ddl.auto", env.getProperty ("hibernate.hbm2ddl.auto")); properties.put ("hibernate.dialect", env.getProperty ("hibernate.dialect")); em.setJpaPropertyMap (מאפיינים); להחזיר אותם; } @Primary @Bean DataSource הציבור userDataSource () {DriverManagerDataSource dataSource = DriverManagerDataSource חדש (); dataSource.setDriverClassName (env.getProperty ("jdbc.driverClassName")); dataSource.setUrl (env.getProperty ("user.jdbc.url")); dataSource.setUsername (env.getProperty ("jdbc.user")); dataSource.setPassword (env.getProperty ("jdbc.pass")); להחזיר dataSource; } @Primary @Bean PlatformTransactionManager ציבורי userTransactionManager () {JpaTransactionManager transactionManager = JpaTransactionManager חדש (); transactionManager.setEntityManagerFactory (userEntityManager (). getObject ()); TransactionManager החזר; }}

שימו לב כיצד אנו משתמשים ב- userTransactionManager כמו שלנו יְסוֹדִי TransactionManager - על ידי הערת הגדרת השעועית עם @יְסוֹדִי. זה מועיל בכל פעם שאנחנו הולכים להזריק במפורש או במפורש את מנהל העסקאות בלי לציין איזה מהם בשם.

לאחר מכן, בואו נדון PersistenceProductConfiguration - שם אנו מגדירים שעועית דומה:

@Configuration @PropertySource ({"classpath: persistence-multiple-db.properties"}) @EnableJpaRepositories (basePackages = "com.baeldung.multipledb.dao.product", entityManagerFactoryRef = "productEntityManager", transactionManagerRefanagerRefanagerRefanagerRefan = "productEntityManager", PersistenceProductConfiguration {@ סביבה פרטית בסביבה פרטית; @Bean LocalContainerEntityManagerFactory ציבורי שעועית ProductEntityManager () {LocalContainerEntityManagerFactoryBean em = חדש LocalContainerEntityManagerFactoryBean (); em.setDataSource (productDataSource ()); em.setPackagesToScan (מחרוזת חדשה [] {"com.baeldung.multipledb.model.product"}); HibernateJpaVendorAdapter vendorAdapter = חדש HibernateJpaVendorAdapter (); em.setJpaVendorAdapter (vendorAdapter); מאפייני HashMap = HashMap חדש (); properties.put ("hibernate.hbm2ddl.auto", env.getProperty ("hibernate.hbm2ddl.auto")); properties.put ("hibernate.dialect", env.getProperty ("hibernate.dialect")); em.setJpaPropertyMap (מאפיינים); להחזיר אותם; } @Bean DataSource ציבורי productDataSource () {DriverManagerDataSource dataSource = DriverManagerDataSource חדש (); dataSource.setDriverClassName (env.getProperty ("jdbc.driverClassName")); dataSource.setUrl (env.getProperty ("product.jdbc.url")); dataSource.setUsername (env.getProperty ("jdbc.user")); dataSource.setPassword (env.getProperty ("jdbc.pass")); להחזיר dataSource; } @Bean פלטפורמה ציבוריתTransactionManager ציבוריתTransactionManager () {JpaTransactionManager transactionManager = JpaTransactionManager חדש (); transactionManager.setEntityManagerFactory (productEntityManager (). getObject ()); TransactionManager החזר; }}

5. מבחן פשוט

לסיום - בואו נבדוק את התצורות שלנו.

ננסה בדיקה פשוטה על ידי יצירת מופע של כל ישות ונוודא שהיא נוצרת - כמו בדוגמה הבאה:

@RunWith (SpringRunner.class) @SpringBootTest @EnableTransactionManagement מחלקה ציבורית JpaMultipleDBIntegrationTest {@ UserRepository פרטי פרטי מאושרים UserRepository; @ מאגר פרטי מוצר מאגר מוצר מאגר; @Test @Transactional ("userTransactionManager") חלל ציבורי כאשרCreatingUser_thenCreated () {משתמש משתמש = משתמש חדש (); user.setName ("ג'ון"); user.setEmail ("[דוא"ל מוגן]"); user.setAge (20); user = userRepository.save (user); assertNotNull (userRepository.findOne (user.getId ())); } @Test @Transactional ("userTransactionManager") בטל ציבורי כאשרCreatingUsersWithSameEmail_thenRollback () {User user1 = משתמש חדש (); user1.setName ("ג'ון"); user1.setEmail ("[מוגן באמצעות הדוא"ל]"); user1.setAge (20); user1 = userRepository.save (user1); assertNotNull (userRepository.findOne (user1.getId ())); משתמש משתמש 2 = משתמש חדש (); user2.setName ("טום"); user2.setEmail ("[דוא"ל מוגן]"); user2.setAge (10); נסה {user2 = userRepository.save (user2); } לתפוס (DataIntegrityViolationException e) {} assertNull (userRepository.findOne (user2.getId ())); } @Test @Transactional ("productTransactionManager") חלל ציבורי כאשרCreatingProduct_thenCreated () {מוצר מוצר = מוצר חדש (); product.setName ("ספר"); product.setId (2); product.setPrice (20); product = productRepository.save (מוצר); assertNotNull (productRepository.findOne (product.getId ())); }}

6. מסדי נתונים מרובים באביב אתחול

Spring Boot יכול לפשט את התצורה לעיל.

כברירת מחדל, Spring Boot יניע את ברירת המחדל שלו מקור מידע עם מאפייני התצורה שקדמו להם spring.datasource. *:

spring.datasource.jdbcUrl = [url] spring.datasource.username = [username] spring.datasource.password = [סיסמה]

כעת אנו רוצים להמשיך להשתמש באותה דרך ל- להגדיר את השני מקור מידע, אך עם מרחב שמות אחר של מאפיינים:

spring.second-datasource.jdbcUrl = [url] spring.second-datasource.username = [username] spring.second-datasource.password = [password]

מכיוון שאנחנו רוצים שהתצורה האוטומטית של Spring Boot תאסוף את המאפיינים השונים האלה (ותתקין שני שונים מקורות מידע), נגדיר שני מחלקות תצורה דומות לאלה שבסעיפים הקודמים:

@Configuration @PropertySource ({"classpath: persistence-multiple-db-boot.properties"}) @EnableJpaRepositories (basePackages = "com.baeldung.multipledb.dao.user", entityManagerFactoryRef = "userEntityManager", UserManagerRanagerRanagerTransmanager מחלקה ציבורית PersistenceUserAutoConfiguration {@Primary @Bean @ConfigurationProperties (קידומת = "spring.datasource") public DataSource userDataSource () {return DataSourceBuilder.create (). build (); } // שעועית userEntityManager // שעועית userTransactionManager}
@Configuration @PropertySource ({"classpath: persistence-multiple-db-boot.properties"}) @EnableJpaRepositories (basePackages = "com.baeldung.multipledb.dao.product", entityManagerFactoryRef = "productEntityManager", transactionmanagerRanagerRanagerRanagerTransManagerRan = מחלקה ציבורית PersistenceProductAutoConfiguration {@Bean @ConfigurationProperties (קידומת = "spring.second-datasource") ציבורי DataSource productDataSource () {להחזיר DataSourceBuilder.create (). build (); } // שעועית productEntityManager // שעועית ProductTransactionManager} 

הגדרנו את מאפייני מקור הנתונים בפנים התמדה- multiple- db-boot. נכסים על פי מוסכמת התצורה האוטומטית של אתחול.

החלק המעניין הוא ביאור לשיטת יצירת שעועית מקור הנתונים @ConfigurationProperties. עלינו רק לציין את קידומת התצורה המתאימה. בתוך שיטה זו, אנו משתמשים ב- DataSourceBuilder, ואתחול האביב ידאג אוטומטית לשאר.

אך כיצד מוזרקים המאפיינים שהוגדרו לתוך מקור מידע תְצוּרָה?

כשמתקשרים ל לִבנוֹת() שיטה על DataSourceBuilder, זה יקרא לפרטי שלה לִקְשׁוֹר() שיטה:

build T ציבורי () {סוג סוג = getType (); תוצאת DataSource = BeanUtils.instantiateClass (סוג); maybeGetDriverClassName (); לאגד (תוצאה); החזרת (T) תוצאה; }

שיטה פרטית זו מבצעת חלק ניכר מקסמי התצורה האוטומטית, ומחייבת את התצורה שנפתרה לממש מקור מידע למשל:

binding void private (תוצאת DataSource) {ConfigurationPropertySource source = MapConfigurationPropertySource חדש (this.properties); ConfigurationPropertyNameAliases aliases = חדש ConfigurationPropertyNameAliases (); aliases.addAliases ("url", "jdbc-url"); aliases.addAliases ("שם משתמש", "משתמש"); קלסר קלסר = קלסר חדש (source.withAliases (כינויים)); binder.bind (ConfigurationPropertyName.EMPTY, Bindable.ofInstance (תוצאה)); }

למרות שאיננו צריכים לגעת באף אחד בקוד זה בעצמנו, עדיין כדאי לדעת מה קורה מתחת למכסה המנוע של התצורה האוטומטית של Spring Boot.

מלבד זאת, תצורת שעועית מנהל העסקה ומנהל הישות זהה ליישום האביב הסטנדרטי.

7. מסקנה

מאמר זה היה סקירה מעשית כיצד להגדיר את פרויקט ה- JPA של Spring Data שלך לשימוש במסדי נתונים מרובים.

ה יישום מלא של מאמר זה ניתן למצוא בפרויקט GitHub - זהו פרויקט מבוסס Maven, כך שיהיה קל לייבא ולהפעיל אותו כפי שהוא.


$config[zx-auto] not found$config[zx-overlay] not found