ORM思想
操作实体类就相当于操作数据库表。
就要建立两个映射关系:
- 建立实体类和表的关系。
- 建立实体类中属性和表中字段的关系。
不再关注重点:SQl语句
实现了ORM思想的框架:Mybatis、Hibernate。
配置两个映射关系:
@ToString
@Data//get和set方法
/**
* 注意!!!:导包都是javax.persistence的包
* 1、完成实体类和表的映射关系
* @Entity 声明实体类
* @Table 配置实体类和表的映射关系
* name:配置数据库表的名称
* 2、实体类中属性和表中字段的关系
*
*/
@Entity
@Table(name = "cst_customer")
public class Customer {
/**
* @Id 声明主键的配置
* @GeneratedValue 配置主键的策略
* (strategy = GenerationType.IDENTITY) 自增
* @Column 配置属性数据表中字段的映射关系
* name:数据库表中字段的名称
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long cust_id;
@Column(name = "cust_name")
private String cust_name;
@Column(name = "cust_source")
private String cust_source;
@Column(name = "cust_industry")
private String cust_industry;
@Column(name = "cust_level")
private String cust_level;
@Column(name = "cust_address")
private String cust_address;
@Column(name = "cust_phone")
private String cust_phone;
}
其中主键的生成策略:
* @GeneratedValue 配置主键的策略
* strategy
* GenerationType.IDENTITY: 自增 (底层数据库必须要支持自动增长)Mysql
* GenerationType.SEQUENCE: 序列 (底层数据库必须支持序列) Oracle
* GenerationType.TABLE : Jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增 相当于除了你的表,他会自己再建一个表来放下一次的自增id为多少
* GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
测试代码:
/**
* 测试jpa的保存
* 案例:保存一个客户到数据库
* Jpa的操作
* 1.加载配置文件创建工厂(实体管理类工厂)对象
* 2.通过实体类管理类工厂获取实体类管理器
* 3.获取事务对象,开启事务
* 4.完成增删改查操作
* 5.提交事务(回滚事务)
* 6.释放资源
*/
@Test
void JpaTest() {
//1.加载配置文件创建工厂(实体管理类工厂)对象
/*维护了很多内容:浪费资源
*线程安全,多个线程访问同一个不会有线程安全问题
*如何解决资源浪费
*创建一个公共的EntityManagerFactory对象
*静态代码块形式创建
*/
EntityManagerFactory myJpa = Persistence.createEntityManagerFactory("MyJpa");//配置文件中persistence-unit的名字
//2.通过实体类管理类工厂获取实体类管理器
/*
*getTransaction:创建事务对象
*persist:保存
*merge:更新
*remove:删除
* find/getRefrence:根据id查询
*/
EntityManager entityManager = myJpa.createEntityManager();
// 3.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
// 4.完成增删改查操作
Customer customer=new Customer();
customer.setCust_name("cqupt");
customer.setCust_address("南山");
//保存
entityManager.persist(customer);
// 5.提交事务(回滚事务:rollback)
transaction.commit();
// 6.释放资源
entityManager.close();
myJpa.close();
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--需要配置persistence-unit节点
持久化单元:
name:持久化单元名称
transaction-type:事务管理的方式
JTA:分布式事务管理(不同的表在不同的数据库)
RESOURCE_LOCAL:本地事务管理(不同的表在同一数据库)
-->
<persistence-unit name="MyJpa" transaction-type="RESOURCE_LOCAL">
<!-- JPA的实现方式-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!-- 数据库信息
用户名:javax.persistence.jdbc.user
密码:javax.persistence.jdbc.password
驱动:javax.persistence.jdbc.driver
数据库地址:javax.persistence.jdbc.url
-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="19980605"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/syfwfl?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC"/>
<!--可选配置:配置JPA实现方的信息
显示Sql :hibernate.show_sql:false|true
自动创建数据库表:hibernate.hbm2ddl.auto:
create: 程序运行时创建数据库(如果有表先删除表再创建)
update: 程序运行时创建表(如果有表不会创建)
none : 不会创建表
-->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
工具类
为减少实体类工厂资源的浪费,写成静态代码块获取:
public class JpaUtils {
private static final EntityManagerFactory myJpa;
/**
* 解决实体类工厂的资源浪费问题,
* 通过静态代码块,当程序第一次访问时创建一个公共的实体类工厂,后面再访问时直接创建EntityManager就可以了
*
*/
static {
myJpa = Persistence.createEntityManagerFactory("MyJpa");//配置文件中persistence-unit的名字
}
public static EntityManager GetEntityManager(){
//2.通过实体类管理类工厂获取实体类管理器
return myJpa.createEntityManager();
}
}
增、删、改、查、查所有、分页查、条件查、计数:
public static void Insert(){
//SpringApplication.run(JpaApplication.class, args);
/**
* 测试jpa的保存
* 案例:保存一个客户到数据库
* Jpa的操作
* 1.加载配置文件创建工厂(实体管理类工厂)对象
* 2.通过实体类管理类工厂获取实体类管理器
* 3.获取事务对象,开启事务
* 4.完成增删改查操作
* 5.提交事务(回滚事务)
* 6.释放资源
*/
// //1.加载配置文件创建工厂(实体管理类工厂)对象
// EntityManagerFactory myJpa = Persistence.createEntityManagerFactory("MyJpa");//配置文件中persistence-unit的名字
// //2.通过实体类管理类工厂获取实体类管理器
// EntityManager entityManager = myJpa.createEntityManager();
EntityManager entityManager=JpaUtils.GetEntityManager();
// 3.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
// 4.完成增删改查操作
Customer customer=new Customer();
customer.setCust_name("cqupt5");
customer.setCust_address("南山");
//保存
entityManager.persist(customer);
// 5.提交事务(回滚事务)
transaction.commit();
// 6.释放资源
entityManager.close();
// myJpa.close();
}
public static void Find(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager=JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
Customer customer;
/**
* find:根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* Object:查询的主键取值 加L表Long型
* 直接返还查询结果,调用find方法时,就会发送sql语句
* 立即加载
*/
customer=entityManager.find(Customer.class,2L);
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
System.out.println(customer);
}
public static void GetReference(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager=JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
Customer customer;
/**
* getReference:根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* Object:查询的主键取值 加L表Long型
* 当调用查询结果对象的时候,才会发送sql语句
* 延迟加载
*/
customer=entityManager.getReference(Customer.class,2L);
System.out.println(customer);
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
/**
* 删
*/
public static void Remove(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager=JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
/**
* getReference:根据id查询数据
* class:查询数据的结果需要包装的实体类类型的字节码
* Object:查询的主键取值 加L表Long型
* 当调用查询结果对象的时候,才会发送sql语句
* 延迟加载
*/
// i 根据id查询客户
// ii调用remove方法删除
entityManager.remove(entityManager.find(Customer.class,2L));
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
/**
* 更新
*/
public static void Update(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager=JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
// 更新
Customer reference = entityManager.getReference(Customer.class, 1L);
reference.setCust_phone("159456789123");
entityManager.merge(reference);
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
/**
* 查询全部
* jqpl:不支持 select*用法,查询的是实体类全限定名称,直接实体类的类名也行
*/
public static void testFindAll(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager= JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
String jqpl="from Customer";
Query query = entityManager.createQuery(jqpl);//创建Query查询对象,query才是执行jpql的对象
//发送查询,并封装结果信息
List list=query.getResultList();
for (Object c:list)
System.out.println(c.toString());
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
/**
* 排序查询:sql: select*from cst_customer order by cust_id DESC
* jqpl: from Customer order by cust_id DESC
*
* cust_id为实体类中的属性名称
*/
public static void testByOrder(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager= JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
String jqpl="from Customer order by cust_id desc";
Query query = entityManager.createQuery(jqpl);//创建Query查询对象,query才是执行jpql的对象
//发送查询,并封装结果信息
List list=query.getResultList();
for (Object c:list)
System.out.println(c.toString());
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
/**
* 统计总人数
* sql:SELECT count(cust_id) from cst_customer
* jqpl:SELECT count(cust_id) from cst_customer
*/
public static void countNums(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager= JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
String jqpl="SELECT count(cust_id) from Customer";
Query query = entityManager.createQuery(jqpl);
//i创建Query查询对象,query才是执行jpql的对象
//ii对参数赋值
//iii发送查询,并封装结果信息
Object obj=query.getSingleResult();//获取唯一结果
System.out.println(obj);
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
/**
* 分页查询
* sql:select*from cst_customer limit 0,2
* jqpl:from cst_customer
*/
public static void CutPageFind(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager= JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
String jqpl="from Customer";
Query query = entityManager.createQuery(jqpl);
//i创建Query查询对象,query才是执行jpql的对象
//ii对参数赋值
query.setFirstResult(0);//从0开始查 会默认省去0
query.setMaxResults(2);//每次查询两条
//iii发送查询,并封装结果信息
List obj=query.getResultList();
for (Object x:obj)
System.out.println(x);
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
/**
* 条件查询
* 查询客户名称以cq开头的用户,现在对占位符进行了改变,变成?1这种是几个就写第几个,从1开始
* sql:SELECT*FROM cst_customer WHERE cust_name LIKE 'cq%'
* jqpl:FROM Customer WHERE cust_name LIKE 'cq%'
*/
public static void ConditionalQuery(){
//1.根据工具类获取EntityManager对象
EntityManager entityManager= JpaUtils.GetEntityManager();
//2.获取事务对象,开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.完成增删改查操作
String jqpl="FROM Customer WHERE cust_name LIKE ?1";
Query query = entityManager.createQuery(jqpl);
//第一个为索引符的位置,起始为0
query.setParameter(1,"cq%");
List obj=query.getResultList();//获取唯一结果
for (Object x:obj)
System.out.println(x);
//4.提交事务(回滚事务)
transaction.commit();
//5.释放资源
entityManager.close();
}
spring-boot整合jpa
继承了JpaRepository就行,它里面已经有很多方法了。
/**
* JpaRepository是最底的接口,继承它等于有所有,用它来完成对数据库的操作
* JpaRepository<T,ID>第一个T是操作的类型,第二个是ID的类型
*/
public interface UserRepository extends JpaRepository<User,Long> {
}
配置文件:
spring:
datasource:
url: xxx
username: xxx
password: xxx
driver-class-name: com.mysql.cj.jdbc.Driver #5.0以上要cj
jpa:
hibernate:
ddl-auto: update
#create:每次都会创建一张表,
#create-drop 每次断开后都会将表删除,
#update自动创建表结构,没有就创,有就更新,
#validate:验证表结构和我们定义的是否一致,不一致就抛异常
database: mysql #选择数据库为mysql
show-sql: true #打印sql的日志
增、删、改、查、分页查、计数:
@RestController
public class UserController {
@Autowired
UserRepository userRepository;
@GetMapping("/user/{id}")
public User GetUser(@PathVariable("id")Long id){
return userRepository.findById(id).get();
}
@GetMapping("/user/is")
public User Insert(User user){
//save既可以做新增又可以做插入
userRepository.save(user);
return user;
}
@GetMapping("/user/up/{id}")
public User Update(@PathVariable("id")Long id, @RequestParam("name")String name){
User user= userRepository.findById(id).get();
user.setName(name);
userRepository.saveAndFlush(user);
return user;
}
@GetMapping("/user/re/{id}")
public User Remove(@PathVariable("id")Long id){
User user= userRepository.findById(id).get();
userRepository.delete(user);
return user;
}
}
/**
* @return 查询全部
*/
@GetMapping("/user/all")
public List<User> findAll(){
List<User>list=userRepository.findAll();
return list;
}
/**
* @return 分页查询
*/
@GetMapping("/user/pa")
public Page<User> findPage(@RequestParam("start")int start,@RequestParam("size")int size){
/* pageNo:页码(从0开始)
size:每页条数
direction:排序标识,即ASC或DESC
name:需要排序的字段*/
PageRequest pageable = PageRequest.of(start,size);
return userRepository.findAll(pageable);
}
/**
* @return 计数
*/
@GetMapping("/user/count")
public Long count(){
return userRepository.count();
}