Jpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范。它为 Java 开发人员提供了一种对象/关联映射工具来管理 Java 应用中的关系数据。它的出现主要是为了简化现有的持久化开发工作和整合 ORM 技术,结束现在 Hibernate,TopLink,JDO 等 ORM 框架各自为营的局面。
值得注意的是,Jpa是在充分吸收了现有 Hibernate,TopLink,JDO 等 ORM 框架的基础上发展而来的,具有易于使用,伸缩性强等优点。从目前的开发社区的反应上看,Jpa 受到了极大的支持和赞扬,其中就包括了 Spring 与 EJB3. 0的开发团队。
注意:Jpa 是一套规范,不是一套产品,那么像 Hibernate,TopLink,JDO 他们是一套产品,如果说这些产品实现了这个 Jpa 规范,那么我们就可以叫他们为 Jpa 的实现产品。
Spring Boot Jpa 是 Spring 基于 ORM 框架、Jpa 规范的基础上封装的一套 Jpa 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data Jpa 可以极大提高开发效率!
Spring Boot Jpa 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现
基本查询也分为两种,一种是 Spring Data 默认已经实现,一种是根据查询的方法来自动解析成 SQL。
Spring Boot Jpa 默认预先生成了一些基本的CURD的方法,例如:增、删、改等等
继承 JpaRepository
public interface UserRepository extends JpaRepository {
}
一 我们使用首先要引入spring data jpa 的jar包
org.springframework.boot
spring-boot-starter-data-jpa
org.slf4j
jcl-over-slf4j
也要引入druid的jar包
com.alibaba
druid
1.1.10
二、要在 application.properties 配置文件中配置两个数据源的一些信息
#first datasource
spring.datasource.first.url=jdbc:oracle:thin:@//ip1:1521/ORCL
spring.datasource.first.username=name1
spring.datasource.first.password=password1
spring.datasource.first.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.first.test-while-idle=true
spring.datasource.first.test-on-borrow=false
spring.datasource.first.test-on-return=false
spring.datasource.first.validation-query=SELECT 1 FROM DUAL
spring.datasource.first.time-between-eviction-runs-millis=300000
spring.datasource.first.min-evictable-idle-time-millis=1800000
spring.datasource.first.initial-size=5
spring.datasource.first.max-active=50
spring.datasource.first.max-wait=60000
spring.datasource.first.min-idle=5
#second datasource
spring.datasource.second.url=jdbc:oracle:thin:@//ip2:1521/ORCL
spring.datasource.second.username=name2
spring.datasource.second.password=password2
spring.datasource.second.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.second.test-while-idle=true
spring.datasource.second.test-on-borrow=false
spring.datasource.second.test-on-return=false
spring.datasource.second.validation-query=SELECT 1 FROM DUAL
spring.datasource.second.time-between-eviction-runs-millis=300000
spring.datasource.second.min-evictable-idle-time-millis=1800000
spring.datasource.second.initial-size=5
spring.datasource.second.max-active=50
spring.datasource.second.max-wait=60000
spring.datasource.second.min-idle=5
三、开始配置第一数据源也就是第一数据源也就是主数据源
1、配置dataSource的FirstDataSourceConfig类
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
@Configuration
public class FirstDataSourceConfig {
@Bean(name = {"firstDataSource"})
@Qualifier("firstDataSource")
@ConfigurationProperties(prefix = "spring.datasource.first")
@Primary
public DataSource firstDataSource() {
return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
}
/* public DruidDataSource firstDataSource(){
return new DruidDataSource();
}*/
@Bean(name = {"jdbcTemplateDmdb"})
@Primary
public JdbcTemplate jdbcTemplate(@Qualifier("firstDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
2、配置jpa的 repository文件
import java.util.Map;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactoryFirst",
transactionManagerRef = "transactionManagerFirst",
basePackages = {"cn.com.repository"}) //repository所在包的位置
public class RepositoryFirstConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
@Qualifier("firstDataSource")
private DataSource firstDS;
@Bean(name = "entityManagerFirst")
@Primary
public EntityManager entityManagerFirst(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactoryFirst")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryFirst(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(firstDS)
.properties(getVendorProperties(firstDS))
.packages("cn.com.domain") //domain所在包的位置
.persistenceUnit("firstPersistenceUnit")
.build();
}
private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Bean(name = "transactionManagerFirst")
@Primary
PlatformTransactionManager transactionManagerFirst(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryFirst(builder).getObject());
}
}
四、配置第二数据源信息
1、配置dataSource的SecondDataSourceConfig类
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
@Configuration
public class SecondDataSourceConfig {
@Bean(name = {"secondaryDataSource"})
@Qualifier("secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().type(com.alibaba.druid.pool.DruidDataSource.class).build();
}
/* public DruidDataSource secondaryDataSource(){
return new DruidDataSource();
}*/
@Bean(name = {"jdbcTemplateDmdb"})
public JdbcTemplate jdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
2、配置jpa的 repository文件
import java.util.Map;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactorySecondary",
transactionManagerRef = "transactionManagerSecondary",
basePackages = {"cn.com.repository2"}) //repository所在包的位置
public class RepositorySecondaryConfig {
@Autowired
private JpaProperties jpaProperties;
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDS;
@Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondaryDS)
.properties(getVendorProperties(secondaryDS))
.packages("cn.com.domain2") //domain所在包的位置
.persistenceUnit("secondaryPersistenceUnit")
.build();
}
private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
@Bean(name = "transactionManagerSecondary")
PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
五、到此多数据源已经都配置好了,如果需要配置更多数据源以此类推。需要注意的是spring boot jpa 的repository文件配置扫描的包要配置好(repository所在包的位置、domain所在包的位置),不然的话这个数据源在你想要的的作用域是不起作用的。
六、如果我想直接用hibernate的sessionFactory原生的语句查询
1、首先配置hibernate的session新建一个类在需要的类继续此类就行
package cn.com.xxx.common;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
public abstract class MyHibernateDaoSupport {
private static final Logger log = LoggerFactory.getLogger(MyHibernateDaoSupport.class);
private Session session;
@Autowired
private SessionFactory sessionFactory;
private void startOperation() {
try {
session = sessionFactory.openSession();
} catch (Exception e) {
log.error("获取 Hibernate Session 异常", e);
}
}
protected void closeSession() {
if (session != null) {
try {
session.close();
} catch (Exception e) {
log.error("关闭 Hibernate Session 异常", e);
}
}
}
protected Session getSession() throws HibernateException {
if (this.session == null || !this.session.isOpen()) {
startOperation();
}
return session;
}
}
2、springboot配置加载sessionFactory的数据源、咱们已第二数据源为列新建一个配置类
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.persistence.EntityManagerFactory;
@Configuration
public class HibernateConfig {
/**
* entityManagerFactorySecondary 要选择第二数据源的entityManagerFactory
* @param emf
* @return
*/
@Bean
public SessionFactory sessionFactory(@Qualifier("entityManagerFactorySecondary") EntityManagerFactory emf) {
return emf.unwrap(SessionFactory.class);
}
}
3、直接就可以在类中使用session来sql语句操作了
public class DataServiceImpl extends MyHibernateDaoSupport{
@Override
public void getClassDropDown() {
try {
Map map = new HashMap();
List arrayList = new ArrayList();
String sql = "SELECT FLDNAME FROM TABLENAME WHERE FLDNAME IS NOT
NULL GROUP BY FLDNAME ";
SQLQuery sqlQuery = getSession().createSQLQuery(sql);
List listObj = sqlQuery.list();
} catch (Exception e) {
log.error("异常" + e);
} finally {
closeSession();
}
}
}
现在很多druid数据库连接池但是我在网上看到的性能问题是Hakari要比druid好很多,我也没验证过不知道真假在此看到一个网友关于Hakari配置多数据的拿来和Druid多数据源配置对比一下。springBoot1.x版本的数据库连接池不是Hakari,在springBoot2.0版本以后才默认是Hakari。文章链接