JPA
- 一:JPA第一个例子
- 目录结构
- persistence.xml
- 实体类
- 测试类
- 成功运行
- 二:注解
- 主键自增长
- JPQL 语句
- 查询全部 (单表)
- 查询一条
- 一对多查询
- 添加
- 修改
- 删除
- JPQL 语法
- 查询全部
- 占位查询
- 命名查询
- 排序
- 查询部分数据
- 构造器赋值
- 聚合函数
- in
- 函数
- 计算函数
- 分页
- 随着时间的推移市面上涌现了越来越多的ORM框架,那么作为java的官方势必要开始一些动作,于是oracle引入新的JPA ORM规范出于两个原因:
其一,简化现有Java EE和Java SE应用开发工作;其二,oracle希望整合ORM技术,实现天下归一 - 1.JPA是什么: 全称Java Persistence API,通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中
简而言之:用于对象持久化的 API,使得应用程序以统一的方式访问持久层 - 2.那么JPA 与 Hibernate究竟是什么关系呢:
JPA 是一种 ORM 规范,而HIbernate是JPA的一种实现,mybtais也是JPA的一种实现
备注:JPA和HIbernate是同一个人写的
Jpa代码+库表问价
链接:https://pan.baidu.com/s/1cYDKsiIeDQ3FOZTVx8PAew
提取码:7hje
一:JPA第一个例子
目录结构
- 创建Maven项目
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<!--
persistence-unit:负责将固定数量的一组类映射到数据库中
name:该属性是必须填写的,其定义了持久化单元的名字-->
<persistence-unit name="mysql-jpa">
<!-- 2.添加持久化类:就是将带有注解的实体类交给JPA进而实现映射到数据库中 -->
<class>bj.sh.gy.enity.User</class>
<properties>
<!-- 3.设置连库四要素 -->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://127.0.0.1:3306/hibernates" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="root" />
<!-- 5.配置JPA实现产品的基本属性:配置Hibernate的基本属性 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
实体类
package bj.sh.gy.enity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author LXY
* @desc
* @time 2022-10-16 0:59
*/
@Table(name = "user")
@Entity
public class User {
@Id
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
@Column(name = "age")
private int age;
@Column(name = "t_version")
private int t_version;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getT_version() {
return t_version;
}
public void setT_version(int t_version) {
this.t_version = t_version;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
测试类
package bj.sh.gy.Test;
import bj.sh.gy.enity.User;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
/**
* @author LXY
* @desc
* @time 2022-10-16 11:01
*/
public class test {
public static void main(String[] args) {
//1.创建实体管理器工厂
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("mysql-jpa");
//2.创建实体管理器
EntityManager entityManager = entityManagerFactory.createEntityManager();
//3.获取事务
EntityTransaction transaction = entityManager.getTransaction();
//4.开启事务
transaction.begin();
//5.创建一个带有数据的实体类对象
User user = new User();
user.setId(64);
user.setName("王五");
//6.保存实体:类似于HIbernate中的save()方法,但是也有不同的地方,就是在数据库主键自增情况下:若提前设置id属性值,JPA EntityManager 的 persist方法将抛出异常,而Hibernate Session的 save 方法可以执行,将忽略提前设置的id值
entityManager.persist(user);
//7.提交事务
transaction.commit();
//8.关闭JPA的相关对象
entityManager.close();
entityManagerFactory.close();
}
}
成功运行
二:注解
@Data
- @Data 是lombok.Data; 下的,作用是打上这个注解不用写get set 构造器 tostring等方法,自动生成,减少代码书写
@Entity
- 修饰实体类,指明该类将映射到指定的数据表,
@Table
- 当实体类与映射的数据库表名不同名时需要使用 @Table 注解,该注解与 @Entity 注解并列使用,使用其 name 属性指明数据库的表名
@Id
- 标识该属性为主键
@GeneratedValue
- 标注主键的生成策略,通过其 strategy 属性。通常与 @Id 注解一起使用。默认情况下 JPA 会自动选择一个最适合底层数据库的主键生成策略,MySQL 默认为 AUTO
常用策略有:
–IDENTITY:采用数据库 ID自增长的方式来自增主键字段,Oracle 不支持这种方式;
–AUTO: JPA自动选择合适的策略,是默认选项;
–SEQUENCE:通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
–TABLE:通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植
@Column
- 当实体的属性与其映射的数据表的列不同名时使用。其 name 属性用来指明此属性在数据表中对应的列名;unique 属性指明是否为唯一约束;nullable 属性用来指明是否可以为空,false 为不能为空;length 属性指明此列的长度。
创建数据库表
CREATE TABLE `t_customer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`age` int(11) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`Creatad_TIME` datetime(0) DEFAULT NULL,
`email` text CHARACTER SET utf8 COLLATE utf8_general_ci,
`Last_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_customer
-- ----------------------------
INSERT INTO `t_customer` VALUES (1, 18, '2022-10-16', '2022-10-16 00:00:00', '2050599999@qq.com', '李四');
INSERT INTO `t_customer` VALUES (2, 18, '2022-10-16', '2022-10-16 00:00:00', '20505929999@qq.com', '李四2');
INSERT INTO `t_customer` VALUES (3, 18, '2022-10-16', '2022-10-16 12:13:46', '20505929999@qq.com', '李四2');
INSERT INTO `t_customer` VALUES (4, 18, '2022-10-16', '2022-10-16 00:00:00', '2050599999@qq.com', '李四');
INSERT INTO `t_customer` VALUES (5, 18, '2022-10-16', '2022-10-16 12:26:48', '2050599999@qq.com', '李四');
@Column(name=“email”,columnDefinition = “text”) //指明是dtext类型
@Column(name = “Last_name”) //指明字段名@Column(name=“birthday”)
@Temporal(TemporalType.DATE) //指明是data类型@Id //主键id
@Column(name = “id”, nullable = false) //nullable指明字段的值不能重复
@GeneratedValue(strategy = GenerationType.AUTO)//主键生成策略
测试类
public static void main(String[] args) {
//1.创建实体管理器工厂
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("mysql-jpa");
//2.创建实体管理器
EntityManager entityManager = entityManagerFactory.createEntityManager();
//3.获取事务
EntityTransaction transaction = entityManager.getTransaction();
//4.开启事务
transaction.begin();
customer customer=new customer();
customer.setAge(18);
customer.setEmail("2050599999@qq.com");
customer.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
customer.setBirthday(new Date());
customer.setName("李四");
//6.保存实体:类似于HIbernate中的save()方法,但是也有不同的地方,就是在数据库主键自增情况下:若提前设置id属性值,JPA EntityManager 的 persist方法将抛出异常,而Hibernate Session的 save 方法可以执行,将忽略提前设置的id值
entityManager.persist(customer);
//7.提交事务
transaction.commit();
//8.关闭JPA的相关对象
entityManager.close();
entityManagerFactory.close();
}
主键自增长
- 如果使用的主键自增长使用persist会出错
JPQL 语句
查询全部 (单表)
Query nativeQuery = entityManager.createNativeQuery("select * from user ", User.class);
List<User> resultList = nativeQuery.getResultList();
for (User user : resultList) {
System.out.println(user);
}
查询一条
User user = entityManager.find(User.class, 1);
System.out.println(user);
- 另外一种方法
User reference = entityManager.getReference(User.class, 1);
一对多查询
- 创建实体类,Student和classses是多对一的映射关系
- 查询多
Query nativeQuery = entityManager.createNativeQuery("select * from student", Student.class);
List <Student>resultList = nativeQuery.getResultList();
for (Student student : resultList) {
System.out.println(student.getSage());
System.out.println(student.getClasses().getCinfor());
}
- 查询一
Query nativeQuery = entityManager.createNativeQuery("select * from classes", Classes.class);
List <Classes> resultList = nativeQuery.getResultList();
for (Classes classes : resultList) {
System.out.println(classes.getCinfor());
}
添加
- 单表
User user=new User();
user.setT_version(1);
user.setAge(15);
user.setName("李先锋");
entityManager.persist(user);
- 一对多
Classes classes=new Classes();
classes.setCid(UUID.randomUUID().toString());
classes.setCinfor("教室");
entityManager.merge(classes); //先进行查询,如果没有就添加
Student student=new Student();
student.setId(UUID.randomUUID().toString());
student.setSage("18");
student.setSname("李现");
Classes classes=new Classes();
classes.setCid("3fd429e4-487c-45e2-ac76-26ad19fc07c9");
student.setClasses(classes);
entityManager.merge(student); //先进行查询,如果没有就添加
修改
- 单表和多表一样
Classes reference = entityManager.getReference(Classes.class, "4028f48183da2d760183da2d77b50000");
reference.setCinfor("教室8");
删除
Classes reference = entityManager.getReference(Classes.class, "3fd429e4-487c-45e2-ac76-26ad19fc07c9");
entityManager.remove(reference);
- 思考:为什么有主外键关系可以直接删除呢,
JPQL 语法
查询全部
Query query = entityManager.createQuery("select u from bj.sh.gy.enity.User u ");
List<User> resultList = query.getResultList();
for (User user : resultList) {
System.out.println(user);
}
占位查询
JPQL 语句支持两种方式的参数定义方式 : 命名参数和位置参数 。 。在同一个查询语句中只允许使用一种参数定义方式
Query query = entityManager.createQuery("select u from bj.sh.gy.enity.User u where u.id=:id");
query.setParameter("id",1);
List resultList = query.getResultList();
System.out.println(resultList.get(0));
Query query = entityManager.createQuery("select u from bj.sh.gy.enity.User u where u.id=?1");
query.setParameter(1, 1);
List resultList = query.getResultList();
System.out.println(resultList.get(0));
命名查询
- 以在实体 bean 上通过 @NamedQuery or @NamedQueries 预先定义一个或多个查询语句,
Query query = entityManager.createNamedQuery("getUser");
List resultList = query.getResultList();
System.out.println(resultList);
排序
Query query = entityManager.createQuery("select u from bj.sh.gy.enity.User u order by u.age desc ");
List resultList = query.getResultList();
System.out.println(resultList);
查询部分数据
Query query = entityManager.createQuery("select u.age,u.name from bj.sh.gy.enity.User u ");
List<Object[]> list = query.getResultList();//因为只是查询的是Customer表中的一个列name,所以此时List 集合中的元素不再是 Customer整体这个对子昂, 而是一个 Object[] 对象数组
for (Object[] objects : list) {
System.out.print(objects[0]);
System.out.println(objects[1]);
}
构造器赋值
Query query = entityManager.createQuery("select new bj.sh.gy.enity.User( u.name,u.age) from bj.sh.gy.enity.User u ");
List <User>resultList = query.getResultList();
System.out.println(resultList);
聚合函数
- avg
- min
- count
- sum
- max
Query query = entityManager.createQuery("select count(u) from bj.sh.gy.enity.User u ");
String s = query.getResultList().toString();
System.out.println(s);
in
- in
- BETWEEN…and
- LIKE:
- IS NULL&& IS NOT NULL
- IS EMPTY:IS EMPTY
Query query = entityManager.createQuery("select u from bj.sh.gy.enity.User u where u.age in(15,16) ");
List <User>resultList = query.getResultList();
函数
- CONCAT 字符串拼接
2. SUBSTRING 字符串截取
3. TRIM 去掉空格
4. LOWER 转换成小写
5. UPPER 装换成大写
6. LENGTH 字符串长度
7. LOCATE 字符串定位
Query query = entityManager.createQuery("select concat(u.name ,'ssss') from bj.sh.gy.enity.User u where u.name like '%%%' ");
List <User>resultList = query.getResultList();
System.out.println(resultList);
计算函数
ABS 绝对值
SQRT 平方根
MOD 取余数
SIZE 取集合的数量
Query query = entityManager.createQuery("select abs(u.age*(-1)) from bj.sh.gy.enity.User u where u.name like '%%%' ");
List <User>resultList = query.getResultList();
System.out.println(resultList);
分页
Query query = entityManager.createQuery("select abs(u.age*(-1)) from bj.sh.gy.enity.User u where u.name like '%%%' ");
List <User>resultList = query.setMaxResults(2).setFirstResult(0).getResultList();
System.out.println(resultList);