使用對象-關(guān)系映射持久化數(shù)據(jù)

在數(shù)據(jù)持久化的世界中,JDBC就像自行車坞琴,對于份內(nèi)的工作它能完成的很好哨查。隨著應(yīng)用程序越來越復(fù)雜,對持久化的要求也越來越復(fù)雜剧辐。我們需要將對象的屬性映射到數(shù)據(jù)庫的列上解恰,并且需要自動生成語句和查詢锋八,這樣我們就能從無休止的問號字符串中解脫出來。

一护盈、Hibernate

還是以Spittr應(yīng)用為例來具體闡述Hibernate的使用挟纱。

我們定義Spitter、Spittle兩個實體類腐宋。

package spittr.domain;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

@Entity

public class Spitter {

private Spitter() {}

@Id

@GeneratedValue(strategy=GenerationType.IDENTITY)

private Long id;

? @Column(name="username")

private String username;

? @Column(name="password")

private String password;

? @Column(name="fullname")

private String fullName;

? @Column(name="email")

private String email;

? @Column(name="updateByEmail")

private boolean updateByEmail;

? public Spitter(Long id, String username, String password, String fullName,

? ? ? ? String email, boolean updateByEmail) {

this.id = id;

? ? ? this.username = username;

? ? ? this.password = password;

? ? ? this.fullName = fullName;

? ? ? this.email = email;

? ? ? this.updateByEmail = updateByEmail;

? }

public Long getId() {return id;}

public String getUsername() {return username;}

public String getPassword() {return password; }

public String getFullName() {return fullName;}

public String getEmail() {return email;}

public boolean isUpdateByEmail() {return updateByEmail; }

}


package spittr.domain;

import java.util.Date;

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.ManyToOne;

@Entity

public class Spittle {

private Spittle() {}

@Id

? @GeneratedValue(strategy=GenerationType.IDENTITY)

private Longid;

? @ManyToOne

? @JoinColumn(name="spitter")

private Spitter spitter;

? @Column

? private String message;

? @Column

? private Date postedTime;

? public Spittle(Long id, Spitter spitter, String message, Date postedTime) {

this.id = id;

? ? ? this.spitter = spitter;

? ? ? this.message = message;

? ? ? this.postedTime = postedTime;

? }

public Long getId() {

return this.id;

? }

public String getMessage() {

return this.message;

? }

public Date getPostedTime() {

return this.postedTime;

? }

public Spitter getSpitter() {

return this.spitter;

? }

}

@Entity注解表示這是一個實體類紊服,@Id注解代表這是數(shù)據(jù)表的primary key ,@GeneratedValue代表這是自動生成的列,

@Column注解將數(shù)據(jù)表的一列與類的屬性綁定胸竞,不指定name屬性則代表和變量名相同欺嗤,@ManyToOne注解代表會有多個Spittle參照同一個Spitter,?@JoinColumn注解代表參考spitter列卫枝。

這樣就實現(xiàn)了類屬性和數(shù)據(jù)表項的綁定煎饼。

同樣我們定義SpitterRepository、SpittleRepository接口校赤。

package spittr.db;

import java.util.List;

import spittr.domain.Spittle;

public interface SpittleRepository {

long count();

? List?findRecent();

? List?findRecent(int count);

? Spittle findOne(long id);

? Spittle save(Spittle spittle);

? List?findBySpitterId(long spitterId);

? void delete(long id);

}


package spittr.db;

import java.util.List;

import spittr.domain.Spitter;

public interface SpitterRepository {

long count();

? Spitter save(Spitter spitter);

? Spitter findOne(long id);

? Spitter findByUsername(String username);

? List?findAll();

}

我們先看看如何配置Hibernate 下面是RepositoryTestConfig.java吆玖。

package spittr.db.hibernate4;

import java.io.IOException;

import java.util.Properties;

import javax.inject.Inject;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;

import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;

import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;

import org.springframework.orm.hibernate4.HibernateTransactionManager;

import org.springframework.orm.hibernate4.LocalSessionFactoryBean;

import org.springframework.transaction.PlatformTransactionManager;

import org.springframework.transaction.annotation.EnableTransactionManagement;

import org.springframework.transaction.annotation.TransactionManagementConfigurer;

@Configuration

@EnableTransactionManagement

@ComponentScan

public class RepositoryTestConfigimplements TransactionManagementConfigurer {

@Inject

? private SessionFactorysessionFactory;

? @Bean

? public DataSource dataSource() {

EmbeddedDatabaseBuilder edb =new EmbeddedDatabaseBuilder();

? ? edb.setType(EmbeddedDatabaseType.H2);

? ? edb.addScript("spittr/db/hibernate4/schema.sql");

? ? edb.addScript("spittr/db/hibernate4/test-data.sql");

? ? EmbeddedDatabase embeddedDatabase = edb.build();

? ? return embeddedDatabase;

? }

public PlatformTransactionManager annotationDrivenTransactionManager() {

System.out.println(sessionFactory);

? ? HibernateTransactionManager transactionManager =new HibernateTransactionManager();

? ? transactionManager.setSessionFactory(sessionFactory);

? ? return transactionManager;

? }

@Bean

? public SessionFactory sessionFactoryBean() {

try {

LocalSessionFactoryBean lsfb =new LocalSessionFactoryBean();

? ? ? lsfb.setDataSource(dataSource());

? ? ? lsfb.setPackagesToScan("spittr.domain");

? ? ? Properties props =new Properties();

? ? ? props.setProperty("dialect", "org.hibernate.dialect.H2Dialect");

? ? ? lsfb.setHibernateProperties(props);

? ? ? lsfb.afterPropertiesSet();

? ? ? SessionFactory object = lsfb.getObject();

? ? ? return object;

? ? }catch (IOException e) {

return null;

? ? }

}

}

這里我們聲明它是一個配置類并且啟用了組件掃描和事務(wù)管理。

@Inject和@Autowired基本相同马篮,同樣dataBase bean為數(shù)據(jù)源配置沾乘,annotationDrivenTransactionManager bean 為事務(wù)處理,

使用Hibernate所需要的主要接口時org.hibernate.Session浑测。Session接口提供了基本的數(shù)據(jù)訪問功能翅阵,如保存、更新迁央、刪除以及從數(shù)據(jù)庫加載對象的功能掷匠。通過Hibernate的Session接口,應(yīng)用程序的Repository能夠滿足所有的持久化需求岖圈。

SessionFactory主要負責(zé)Hibernate Session的打開槐雾,關(guān)閉以及管理。

dataSource和hibernateProperties屬性聲明了從哪里獲取數(shù)據(jù)庫連接以及要使用哪一種數(shù)據(jù)庫幅狮。這里不再列出Hibernate配置文件,使用packageToScan屬性告訴Spring掃描一個或多個包以查找域類株灸,這些類表明要使用Hibernate進行持久化崇摄,這些類可以使用的注解包括JPA的@Entity或@MappedSuperclass以及Hibernate的Entity。

了解完Hibernate的配置之后我們開始編寫HibernateSpitterRepository和HibernateSpittleRepository他們分別實現(xiàn)SpitterRepository接口和SpittleRepository接口慌烧。

package spittr.db.hibernate4;

import java.io.Serializable;

import java.util.List;

import javax.inject.Inject;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.criterion.Restrictions;

import org.springframework.stereotype.Repository;

import spittr.db.SpitterRepository;

import spittr.domain.Spitter;

@Repository

public class HibernateSpitterRepository implements SpitterRepository {

private SessionFactory sessionFactory;

@Inject

public HibernateSpitterRepository(SessionFactory sessionFactory) {

this.sessionFactory = sessionFactory; //<co id="co_InjectSessionFactory"/>

}

private Session currentSession() {

return sessionFactory.getCurrentSession();//<co id="co_RetrieveCurrentSession"/>

}

public long count() {

return findAll().size();

}

public Spitter save(Spitter spitter) {

Serializable id = currentSession().save(spitter);? //<co id="co_UseCurrentSession"/>

return new Spitter((Long) id,

spitter.getUsername(),

spitter.getPassword(),

spitter.getFullName(),

spitter.getEmail(),

spitter.isUpdateByEmail());

}

public Spitter findOne(long id) {

return (Spitter) currentSession().get(Spitter.class, id);

}

public Spitter findByUsername(String username) {

return (Spitter) currentSession()

.createCriteria(Spitter.class)

.add(Restrictions.eq("username", username))

.list().get(0);

}

public List<Spitter> findAll() {

return (List<Spitter>) currentSession()

.createCriteria(Spitter.class).list();

}

}


package spittr.db.hibernate4;

import java.io.Serializable;

import java.util.List;

import javax.inject.Inject;

import org.hibernate.Criteria;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.criterion.Order;

import org.hibernate.criterion.Restrictions;

import org.springframework.stereotype.Repository;

import spittr.db.SpittleRepository;

import spittr.domain.Spittle;

@Repository

public class HibernateSpittleRepositoryimplements SpittleRepository {

private SessionFactorysessionFactory;

? @Inject

? public HibernateSpittleRepository(SessionFactory sessionFactory) {

this.sessionFactory = sessionFactory;

? }

private Session currentSession() {

return sessionFactory.getCurrentSession();//

? }

public long count() {

return findAll().size();

? }

public List?findRecent() {

return findRecent(10);

? }

public List?findRecent(int count) {

return (List) spittleCriteria()

.setMaxResults(count)

.list();

? }

public Spittle findOne(long id) {

return (Spittle) currentSession().get(Spittle.class, id);

? }

public Spittle save(Spittle spittle) {

Serializable id = currentSession().save(spittle);

? ? ? return new Spittle(

(Long) id,

? ? ? ? spittle.getSpitter(),

? ? ? ? spittle.getMessage(),

? ? ? ? spittle.getPostedTime());

? }

public List?findBySpitterId(long spitterId) {

return spittleCriteria()

.add(Restrictions.eq("spitter.id", spitterId))

.list();

? }

public void delete(long id) {

currentSession().delete(findOne(id));

? }

public List?findAll() {

return (List) spittleCriteria().list();

? }

private Criteria spittleCriteria() {

return currentSession()

.createCriteria(Spittle.class)

.addOrder(Order.desc("postedTime"));

? }

}

我們將一個SessionFactory注入到HibernateSpitterRepository和HibernateSpittleRepository的sessionFactory屬性中逐抑,在currentSession()方法中我們使用這個sessionFactory來獲取當(dāng)前事務(wù)的Session。

我們使用了@Repository注解屹蚊,它能夠被組件掃描掃描到厕氨,不必顯示聲明进每,它還會捕獲平臺相關(guān)的異常,然后使用Spring統(tǒng)一非檢查型異常重新拋出命斧。

數(shù)據(jù)類同數(shù)據(jù)庫的表存在對應(yīng)關(guān)系田晚,使用Hibernate操作數(shù)據(jù)類時,Hibernate會將之轉(zhuǎn)換為對數(shù)據(jù)庫中對應(yīng)表的操作国葬。

org.hibernate.Criteria接口表示特定持久類的一個查詢贤徒。Session是 Criteria實例的工廠。currentSession()

.createCriteria(Spittle.class)表示Spittle類的一個查詢汇四。參見:http://www.baike.com/wiki/criteria

session.save()方法返回一個生成的id接奈,該id為Serializable類型。

接下來測試一下

package spittr.db.hibernate4;

import static org.junit.Assert.*;

import java.util.List;

import org.junit.BeforeClass;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.springframework.transaction.annotation.Transactional;

import spittr.db.SpitterRepository;

import spittr.domain.Spitter;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes = RepositoryTestConfig.class)

public class SpitterRepositoryTest {

@Autowired

? SpitterRepository spitterRepository;

@Test

@Transactional

? public void findAll() {

List spitters =spitterRepository.findAll();

? ? assertEquals(4, spitters.size());

? ? assertSpitter(0, spitters.get(0));

? ? assertSpitter(1, spitters.get(1));

? ? assertSpitter(2, spitters.get(2));

? ? assertSpitter(3, spitters.get(3));

? }

}

二通孽、JPA-Hibernate

我們嘗試開發(fā)基于JPA的Repository序宦。Java持久化API(Java Persistence API,JPA)誕生在EJB2實體Bean的廢墟之上背苦,并成為下一代Java持久化標(biāo)準(zhǔn)互捌。JPA是基于POJO的持久化機制。

以Spittr應(yīng)用為例糠惫,我們首先看看JPAConfig類

package spittr.db.jpa;

import javax.inject.Inject;

import javax.persistence.EntityManagerFactory;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.ComponentScan;

import org.springframework.context.annotation.Configuration;

import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;

import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;

import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;

import org.springframework.orm.jpa.JpaTransactionManager;

import org.springframework.orm.jpa.JpaVendorAdapter;

import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import org.springframework.orm.jpa.vendor.Database;

import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

import org.springframework.transaction.PlatformTransactionManager;

import org.springframework.transaction.annotation.EnableTransactionManagement;

import org.springframework.transaction.annotation.TransactionManagementConfigurer;

@Configuration

@ComponentScan

public class JpaConfig {

@Bean

? public DataSource dataSource() {

EmbeddedDatabaseBuilder edb =new EmbeddedDatabaseBuilder();

? ? edb.setType(EmbeddedDatabaseType.H2);

? ? edb.addScript("spittr/db/jpa/schema.sql");

? ? edb.addScript("spittr/db/jpa/test-data.sql");

? ? EmbeddedDatabase embeddedDatabase = edb.build();

? ? return embeddedDatabase;

? }

@Bean

? public LocalContainerEntityManagerFactoryBean emf(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {

LocalContainerEntityManagerFactoryBean emf =new LocalContainerEntityManagerFactoryBean();

? ? emf.setDataSource(dataSource);

? ? emf.setPersistenceUnitName("spittr");

? ? emf.setJpaVendorAdapter(jpaVendorAdapter);

? ? emf.setPackagesToScan("spittr.domain");

? ? return emf;

? }

@Bean

? public JpaVendorAdapter jpaVendorAdapter() {

HibernateJpaVendorAdapter adapter =new HibernateJpaVendorAdapter();

? ? adapter.setDatabase(Database.H2);

? ? adapter.setShowSql(true);

? ? adapter.setGenerateDdl(false);

? ? adapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect");

? ? return adapter;

? }

@Configuration

@EnableTransactionManagement

? public static class TransactionConfig implements TransactionManagementConfigurer {

@Inject

? ? private EntityManagerFactory emf;

? ? public PlatformTransactionManager annotationDrivenTransactionManager() {

JpaTransactionManager transactionManager =new JpaTransactionManager();

? ? ? transactionManager.setEntityManagerFactory(emf);

? ? ? return transactionManager;

? ? }

}

}

基于JPA的應(yīng)用程序需要使用EntityManagerFactory的實現(xiàn)類來獲得EntityManager實例疫剃。JPA定義了應(yīng)用程序管理類型和容器管理類型的實體管理器,這兩種實體管理器實現(xiàn)了同一個EntityManager接口硼讽。關(guān)鍵的區(qū)別不在于EntityManager本身巢价,而是在于EntityManager的創(chuàng)建和管理方式。顧名思義固阁,前者由應(yīng)用程序創(chuàng)建和管理壤躲,后者由Java EE創(chuàng)建和管理。

JpaVendorAdapter 屬性用于指明所使用的是哪一個廠商的JPA實現(xiàn)备燃。

使用LocalContainerEntityManagerFactoryBean來配置容器管理類型的JPA碉克。

接下來編寫基于JPA的Repository:JpaSpitterRepository、JpaSpittleRepository

package spittr.db.jpa;

import java.util.List;

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

import spittr.db.SpitterRepository;

import spittr.domain.Spitter;

@Repository

public class JpaSpitterRepository implements SpitterRepository {

@PersistenceContext

? private EntityManager entityManager;

? public long count() {

return findAll().size();

? }

public Spitter save(Spitter spitter) {

entityManager.persist(spitter);

? ? ? return spitter;

? }

public Spitter findOne(long id) {

return entityManager.find(Spitter.class, id);

? }

public Spitter findByUsername(String username) {

return (Spitter)entityManager.createQuery("select s from Spitter s where s.username=?").setParameter(1, username).getSingleResult();

? }

public List?findAll() {

return (List)entityManager.createQuery("select s from Spitter s").getResultList();

? }

}


package spittr.db.jpa;

import java.util.List;

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

import spittr.db.SpittleRepository;

import spittr.domain.Spittle;

@Repository

public class JpaSpittleRepository implements SpittleRepository {

@PersistenceContext

? private EntityManager entityManager;

? public long count() {

return findAll().size();

? }

public List?findRecent() {

return findRecent(10);

? }

public List?findRecent(int count) {

return (List)entityManager.createQuery("select s from Spittle s order by s.postedTime desc")

.setMaxResults(count)

.getResultList();

? }

public Spittle findOne(long id) {

return entityManager.find(Spittle.class, id);

? }

public Spittle save(Spittle spittle) {

entityManager.persist(spittle);

? ? return spittle;

? }

public List?findBySpitterId(long spitterId) {

return (List)entityManager.createQuery("select s from Spittle s, Spitter sp where s.spitter = sp and sp.id=? order by s.postedTime desc")

.setParameter(1, spitterId)

.getResultList();

? }

public void delete(long id) {

entityManager.remove(findOne(id));

? }

public List?findAll() {

return (List)entityManager.createQuery("select s from Spittle s").getResultList();

? }

}

由于EntityManager并不是線程安全的并齐,一般并不適合注入到Repository這樣共享的單例Bean中漏麦,我們使用@PersistanceContext注解解決這個問題。@PersistanceContext并沒有注入一個真正的EntityManager况褪,而是給了它一個EntityManager的代理撕贞。真正的EntityManager是與當(dāng)前事務(wù)相關(guān)聯(lián)的那一個,如果不存在测垛,就會創(chuàng)建一個新的捏膨。@Transactional表明這個Repository中的持久化方法是在事務(wù)上下文中執(zhí)行的。

以下是測試類部分代碼:

package spittr.db.jpa;

import static org.junit.Assert.*;

import java.util.List;

import org.junit.BeforeClass;

import org.junit.Ignore;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.springframework.transaction.annotation.Transactional;

import spittr.db.SpitterRepository;

import spittr.domain.Spitter;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes=JpaConfig.class)

public class SpitterRepositoryTest {

@Autowired

? SpitterRepository spitterRepository;

@Test

@Transactional

? public void findAll() {

List spitters =spitterRepository.findAll();

? ? ? assertEquals(4, spitters.size());

? ? ? assertSpitter(0, spitters.get(0));

? ? ? assertSpitter(1, spitters.get(1));

? ? ? assertSpitter(2, spitters.get(2));

? ? ? assertSpitter(3, spitters.get(3));

? }

}

三、借助Spring Data實現(xiàn)自動化的JPA Repository

盡管JPA-Hibernate代碼已經(jīng)很簡單号涯,但依然會有直接與EntityManager交互來查詢數(shù)據(jù)庫目胡。我們借助Spring Data,以接口定義的方式創(chuàng)建Repository链快。

package spittr.db;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import spittr.domain.Spittle;


public interface SpittleRepositoryextends JpaRepository, SpittleRepositoryCustom {

ListfindBySpitterId(long spitterId);

}


package spittr.db;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import spittr.domain.Spitter;

public interface SpitterRepository extends JpaRepository, SpitterSweeper {

Spitter findByUsername(String username);

List findByUsernameOrFullNameLike(String username, String fullName);

}

這里我們并不需要實現(xiàn)findBySpittleId方法誉己,findByUsername方法,findByUsernameOrFullNameLike方法久又,方法簽名已經(jīng)告訴Spring Data JPA足夠的信息來創(chuàng)建這個方法的實現(xiàn)了巫延。

編寫Spring Data JPA Repository 的關(guān)鍵在于要從一組接口中選一個進行擴展,這里SpittleRepository擴展了Spring Data JPA 的JpaRepository地消。通過這種方式炉峰,JpaRepository進行了參數(shù)化,所以它就能知道這是一個用來持久化Spitter對象的Repository脉执,并且Spitter對象的ID類型為Long疼阔。

接下來我們看看自定義查詢方法。

package spittr.db;

public interface Spitter Sweeper {

int eliteSweep();

}

package spittr.db;

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

public class SpitterRepositoryImpl implements SpitterSweeper {

@PersistenceContext

? private EntityManager em;

? public int eliteSweep() {

String update =

"UPDATE Spitter spitter " +

"SET spitter.status = 'Elite' " +

"WHERE spitter.status = 'Newbie' " +

"AND spitter.id IN (" +

"SELECT s FROM Spitter s WHERE (" +

"? SELECT COUNT(spittles) FROM s.spittles spittles) > 10000" +

")";

? ? ? return em.createQuery(update).executeUpdate();

? }

}

復(fù)雜查詢可以自己編寫半夷。

配置Spring Data? JPA

package spittr.db;

import javax.sql.DataSource;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;

import org.springframework.orm.jpa.JpaTransactionManager;

import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

import org.springframework.orm.jpa.vendor.Database;

import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

@Configuration

@EnableJpaRepositories("spitter.db")

public class SpringDataJpaConfig {

@Bean

? public DataSourcedataSource() {

return new EmbeddedDatabaseBuilder()

.addScript("classpath:/com/habuma/spitter/db/jpa/schema.sql")

.addScript("classpath:/com/habuma/spitter/db/jpa/test-data.sql")

.build();

? }

@Bean

? public JpaTransactionManagertransactionManager() {

return new JpaTransactionManager(); // does this need an emf???

? }

@Bean

? public HibernateJpaVendorAdapterjpaVendorAdapter() {

HibernateJpaVendorAdapter adapter =new HibernateJpaVendorAdapter();

? ? adapter.setDatabase(Database.H2);

? ? adapter.setShowSql(false);

? ? adapter.setGenerateDdl(true);

? ? return adapter;

? }

@Bean

? public Objectemf() {

LocalContainerEntityManagerFactoryBean emf =new LocalContainerEntityManagerFactoryBean();

? ? emf.setDataSource(dataSource());

? ? emf.setPersistenceUnitName("spitter");

? ? emf.setJpaVendorAdapter(jpaVendorAdapter());

? ? return emf;

? }

}

@EnableJpaRepositories("spitter.db")會掃描spittr.db包查找擴展自Spring Data JPA Repository接口的所有接口婆廊,如果發(fā)現(xiàn)了擴展自Repository的接口,他會自動(在應(yīng)用啟動的時候)生成這個接口的實現(xiàn)巫橄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淘邻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子湘换,更是在濱河造成了極大的恐慌宾舅,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彩倚,死亡現(xiàn)場離奇詭異筹我,居然都是意外死亡,警方通過查閱死者的電腦和手機帆离,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門蔬蕊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人哥谷,你說我怎么就攤上這事岸夯。” “怎么了们妥?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵猜扮,是天一觀的道長。 經(jīng)常有香客問我王悍,道長,這世上最難降的妖魔是什么餐曼? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任压储,我火速辦了婚禮鲜漩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘集惋。我一直安慰自己孕似,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布刮刑。 她就那樣靜靜地躺著喉祭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雷绢。 梳的紋絲不亂的頭發(fā)上泛烙,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機與錄音翘紊,去河邊找鬼蔽氨。 笑死,一個胖子當(dāng)著我的面吹牛帆疟,可吹牛的內(nèi)容都是我干的鹉究。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼踪宠,長吁一口氣:“原來是場噩夢啊……” “哼自赔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起柳琢,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绍妨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后染厅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痘绎,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年肖粮,在試婚紗的時候發(fā)現(xiàn)自己被綠了孤页。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡涩馆,死狀恐怖行施,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情魂那,我是刑警寧澤蛾号,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站涯雅,受9級特大地震影響鲜结,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一精刷、第九天 我趴在偏房一處隱蔽的房頂上張望拗胜。 院中可真熱鬧,春花似錦怒允、人聲如沸埂软。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勘畔。三九已至,卻和暖如春丽惶,著一層夾襖步出監(jiān)牢的瞬間炫七,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工蚊夫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诉字,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓知纷,卻偏偏與公主長得像壤圃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子琅轧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容