参考文章:spring boot整合hibernate 连接 Oracle
JPA,Java Persistence Api,中文译名为:Java持久层Api。是一个基于ORM(或叫O/R mapping ,对象关系映射)的标准规范,在这个规范中,JPA只定义标准规则,不提供实现。目前,JPA的主要实现有Hibernate,EclipseLink,OpenJPA等。
由于Hibernate在数据访问解决技术领域的霸主地位,所以JPA标准基本由Hibernate主导。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--阿里druid数据库链接依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
<!--事务管理--原子性,一致性,隔离性,持久性-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--使用mysql时引入-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--使用postgresql时引入-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
# postgresql 环境配置
server:
port: 18005
max-http-header-size: 8192
logging:
level:
root: info
spring:
datasource:
url: jdbc:postgresql://10.101.15.59:5432/postgres
username: root
password: 123abc
driverClassName: org.postgresql.Driver
platform: postgres
type: com.alibaba.druid.pool.DruidDataSource
# type: org.apache.commons.dbcp2.BasicDataSource
initialization-mode: always
# ============================== druid ============================== #
druid:
#最大活跃数
maxActive: 20
#初始化数量
initialSize: 1
#最大连接等待超时时间
maxWait: 60000
#打开PSCache,并且指定每个连接PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
#通过connectionProperties属性来打开mergeSql功能;慢SQL记录
#connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 1 from dual
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
#配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙
filters: stat, wall, log4j
# ============================= spring jpa 配置 ============================= #
jpa:
show_sql: true
database-platform: org.hibernate.dialect.PostgreSQL9Dialect
# database-platform: cn.luutqf.springboot.dialect.JsonbPostgresDialect
hibernate:
ddl-auto: update # none: 关闭hibernate的自动创建表结构的机制
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
hbm2ddl.auto: update
jdbc.lob.non_contextual_creation: true
format_sql: true
temp:
# 兼容SpringBoot2.X, 关闭 Hibernate尝试验证PostgreSQL的CLOB特性
use_jdbc_metadata_defaults: false
package org.fiend.config;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
/**
* postgresql data source config
* @author fiend 2018/12/5
*/
@Configuration
public class DataSourceConfig {
// @Primary
@Bean(name="dataSource")
@ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().type(dataSourceType).build();
}
@Value("${spring.datasource.type}")
private Class<? extends DataSource> dataSourceType;
/**
* 配置监控服务器
* @return 返回监控注册的servlet对象
*/
@Bean
@SuppressWarnings("unchecked")
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean servletRegistrationBean =
new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
// 添加IP白名单
servletRegistrationBean.addInitParameter("allow", "192.168.25.125,127.0.0.1");
// 添加IP黑名单,当白名单和黑名单重复时,黑名单优先级更高
servletRegistrationBean.addInitParameter("deny", "192.168.25.123");
// 添加控制台管理用户
servletRegistrationBean.addInitParameter("loginUsername", "druid");
servletRegistrationBean.addInitParameter("loginPassword", "123456");
// 是否能够重置数据
servletRegistrationBean.addInitParameter("resetEnable", "false");
return servletRegistrationBean;
}
/**
* 配置服务过滤器
* @return 返回过滤器配置对象
*/
@Bean
@SuppressWarnings("unchecked")
public FilterRegistrationBean statFilter() {
FilterRegistrationBean filterRegistrationBean=new FilterRegistrationBean(new WebStatFilter());
// 添加过滤规则
filterRegistrationBean.addUrlPatterns("/*");
// 忽略过滤格式
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*,");
return filterRegistrationBean;
}
}
package org.fiend.entity;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author fiend 2018/12/5
*/
@Entity
@Table(catalog="public", name="user")
public class User implements Serializable { //序列化在Jpa需要
// @Id是用来标识主键的,而@GeneratedValue则是用来指定主键策略的
@Id
@GeneratedValue
private String name;
// @Column(name = "count", nullable = false)
private Integer count;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
package org.fiend.repository;
import org.fiend.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import javax.transaction.Transactional;
import java.util.LinkedHashMap;
import java.util.List;
/**
* @author langpf 2018/12/10
*/
@Repository
public interface UserRepository extends JpaRepository<User, String> {
/**
* 进行数据库操作, 可以通过自定义HQL来完成符合个性的其他操作
* 通过@Query注解, 完成了HQL的书写, 其中“:name”与下方的@Param注解中参数保持一致。
* HQL可使用Hibernate的SQL生成和缓存策略
* HQL中一些关键字如 SELECT, FROM 和 WHERE等, 是不区分大小写的, 但是一些属性如表名和列名区分大小写
*/
@Query(value = "SELECT u FROM User u WHERE name=:name")
User findName(@Param("name") String name);
/**
* 使用SQL语句, nativeQuery为true代表使用SQL语言
* 建议尽可能的使用HQL语句, 以避免数据库关于可移植性的麻烦, 且HQL可使用Hibernate的SQL生成和缓存策略。
*/
@Query(value = "insert into User value(?,?,?)", nativeQuery = true)
@Transactional
@Modifying
int countUserBy(@Param("id") Integer id, @Param("name") String name,
@Param("password") String password);
/**
* 根据用户名查询
*/
@Query("select t from User t where t.name = :name")
User findByUserName(@Param("name") String name);
/**
* 查询全部
*/
@Query("select t from User t")
List<User> find();
/**
* 删除, 必须加入@Modifying和@Transactional
*/
@Modifying
@Transactional
@Query("delete from User u where u.id=:id")
int deleteUserById(@Param("id") Integer id);
@Modifying
@Transactional
@Query("update User u set u.name = :name where u.id=:id")
int queryUserById(@Param("id") Integer id, @Param("name") String name);
/* =========================== 分页查询等 =========================== */
/**
* 根据表名, 字段, 参数查询, 拼接sql语句
* @param tableName 表名
* @param filed 字段名
* @param o 字段参数
*/
List<User> findByHql(String tableName, String filed, Object o);
Object findObjiectByHql(String tableName, String filed, Object o);
/**
* 多个字段的查询
* @param tableName 表名
* @param map 将你的字段传入map中
*/
List<User> findByMoreFiled(String tableName, LinkedHashMap<String, Object> map);
/**
* 多字段查询分页
* @param tableName 表名
* @param map 以map存储key,value
* @param star 第几页
* @param pageNumber 一个页面的条数
*/
List<User> findByMoreFiledPage(String tableName, LinkedHashMap<String, Object> map,
int star, int pageNumber);
/**
* 一个字段的分页
* @param tableName 表名
* @param filed 字段名
* @param o 字段参数
* @param start 第几页
* @param pageNumber 一个页面多少条数据
*/
List<User> findPages(String tableName, String filed, Object o, int start, int pageNumber);
/**
* 根据传入的map遍历key,value拼接字符串, 以id为条件更新
* @param tableName 表名
* @param map 传入参数放入map中
*/
Integer updateMoreFiled(String tableName, LinkedHashMap<String, Object> map,
Long id);
/**
* 根据条件查询总条数返回object类型
* @param tableName 表名
* @param map 传入参数放入map中
*/
Object findCount(String tableName, LinkedHashMap<String, Object> map);
}
package org.fiend.service;
import com.alibaba.fastjson.JSONObject;
import org.fiend.base.AbstractService;
import org.fiend.entity.User;
import org.fiend.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Administrator
*/
@Service
public class HomeService extends AbstractService {
Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private UserRepository userRepository;
public JSONObject getUserList() {
JSONObject json = new JSONObject();
List<User> userList = userRepository.find();
json.put("userList", userList);
return json;
}
public JSONObject getUserList1() {
JSONObject json = new JSONObject();
List<User> userList = userRepository.findAll();
json.put("userList", userList);
return json;
}
public List<User> find() {
List<User> list = null;
try {
list = userRepository.find();
} catch (Exception e) {
}
return list;
}
public String deleteUserById(Integer id){
int a = userRepository.deleteUserById(id);
return "chenggong";
}
public String queryUserById(Integer id ,String name){
int a = userRepository.queryUserById(id,name);
return "成功";
}
public String countUserBy(Integer id ,String name ,String password){
int a = userRepository.countUserBy(id,name,password);
return "成功";
}
}
package org.fiend.controller;
import com.alibaba.fastjson.JSONObject;
import org.fiend.base.AbstractController;
import org.fiend.service.HomeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.inject.Inject;
import javax.inject.Named;
/**
* @author Administrator
*/
@Controller
@RequestMapping(value = "home")
public class HomeController extends AbstractController<HomeService> {
Logger log = LoggerFactory.getLogger(this.getClass());
@Override
@Inject
@Named("homeService")
protected void setService(HomeService service) {
this.service = service;
}
@RequestMapping(value = "getUserList")
@ResponseBody
public JSONObject getUserList() {
return service.getUserList();
}
@RequestMapping(value = "getUserList1")
@ResponseBody
public JSONObject getUserList1() {
return service.getUserList1();
}
}
Repository文件注解说明:
@modifying:
(1)可以通过自定义的JPQL完成UPDATE和DELETE操作。 注意:JPQL不支持使用INSERT;
(2)在@Query注解中编写JPQL语句,但必须使用@Modifying修饰,以通知SpringData这是一个UPDATE 或 DELETE操作
(3)UPDATE 或 DELETE操作需要使用事务,此时需要定义Service层,在Service层的方法上添加事务操作;
(4)默认情况下,SpringData的每个方法上有事务,但都是一个只读事务。
@Transactional:
A. 一个功能是否要事务,必须纳入设计、编码考虑。不能仅仅完成了基本功能就ok。
B. 如果加了事务,必须做好开发环境测试(测试环境也尽量触发异常、测试回滚),确保事务生效。
C. 以下列了事务使用过程的注意事项,请大家留意。
1.不要在接口上声明@Transactional ,而要在具体类的方法上使用 @Transactional 注解,否则注解可能无效。
2.不要图省事,将@Transactional放置在类级的声明中,放在类声明,会使得所有方法都有事务。
故@Transactional应该放在方法级别,不需要使用事务的方法,就不要放置事务,比如查询方法。
否则对性能是有影响的。
3.使用了@Transactional的方法,对同一个类里面的方法调用,
@Transactional无效。比如有一个类Test,它的一个方法A,A再调用Test本类的方法B
(不管B是否public还是private),但A没有声明注解事务,而B有。
则外部调用A之后,B的事务是不会起作用的。(经常在这里出错)
4.使用了@Transactional的方法,只能是public,
@Transactional注解的方法都是被外部其他类调用才有效,故只能是public。
道理和上面的有关联。故在protected、private 或者 package-visible 的方法上使用 @Transactional
注解,它也不会报错,但事务无效。
5.经过在ICORE-CLAIM中测试,效果如下:
A.抛出受查异常XXXException,事务会回滚。
B.抛出运行时异常NullPointerException,事务会回滚。
C.Quartz中,execute直接调用加了@Transactional方法,可以回滚;
间接调用,不会回滚。(即上文3点提到的)
D.异步任务中,execute直接调用加了@Transactional方法,可以回滚;
间接调用,不会回滚。(即上文3点提到的)
E.在action中加上@Transactional,不会回滚。切记不要在action中加上事务。
F.在service中加上@Transactional,如果是action直接调该方法,会回滚,如果是间接调,不会回滚。
(即上文3提到的)
G.在service中的private加上@Transactional,事务不会回滚。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://fiend.blog.csdn.net/article/details/84944338
内容来源于网络,如有侵权,请联系作者删除!