摘要:说明首先来说是一个持久化规范,也就是说当我们用的时候我们不需要去选面向的编程了,这样就大大降低了偶和度了引入是一种规范,那么它的编程有哪些要求呢引入下载的包导入文件夹,然后我们的在下面加上一个目录在该文件夹下面加上一个文件,这个文件的规范
说明
首先来说JPA是一个持久化规范,也就是说当我们用jpa的时候我们不需要去选面向hibernate的api编程了,这样就大大降低了偶和度了
引入JPA是一种规范,那么它的编程有哪些要求呢?
引入下载的jar包导入lib文件夹,然后我们的在src下面加上一个META-INF目录在该文件夹下面加上一个persistence.xml文件,这个文件的规范写法
org.hibernate.ejb.HibernatePersistence
这个文件中的写话我们可以再hibernate的jpa实现包里面找到对应的例子,这里我是使用的是hibernate来实现JPA实现,上面的配置也都和heibernate差不太多值得注意的:
Persistence-unit持久性化单元,我们可以随便命名但是在后面回到他的,通过它来找到相关的配置信息
transaction-type 是指事物的类型,在通常情况下我们是本地的,但是当我们遇到两个数据库保存的时候 我们会到到JTA事物来控制事务,也就是二次提交
实体类来映射数据表Persion.java
@Entity //就是告诉JPA我是一个实体bean @Table(name="t_person")//作为修改表名,默认情况是类名 public class Person { /** * GenerationType.AUTO它会根据数据库方言来选择正确的生成策略 * 默认情况下就是AUTO */ @Id//映射主键 @GeneratedValue(strategy=GenerationType.AUTO) private Integer id; // 映射一列到数据库中 length是指字段的长度 // nullable是指是否为空,默认情况是空 // 当我们不想让类字段名与数据库名一样的时候用到的 @Column(length=10,nullable=false,name="personname") private String name; // 映射日期类型TemporalType有好几种映射方式 // 我们可以根据自己的需求选择正确的映射方式 @Temporal(TemporalType.DATE) @Column(nullable=false) private Date birthday; // 用枚举类型来映射性别EnumType有好几种映射方式 // 这里使用的是枚举的String类型,我们也一个选择枚举的索引 @Enumerated(EnumType.STRING) @Column(nullable=false,length=5) private Sex sex = Sex.MEN; // 对应大文本和图片就是二进制 @Lob private String info; // 支持延迟加载(减少内存的消耗) @Lob @Basic(fetch=FetchType.LAZY) private Byte[] image; // 不想这个字段与数据库表映射 @Transient private String imagepath; // 版本标识 防止脏读 @Version private Integer version; // get set // }利用jpa来操作数据库
Test.java
@Test public void testSave() { /** * jun是在persistence.xml中持久化单元名称 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); //--->>SessionFactory-->>session-->>begin EntityManager em = factory.createEntityManager(); em.getTransaction().begin();//开启事物 Person person = new Person("刘文军"); person.setBirthday(new Date()); em.persist(person); System.out.println("----->>"+person.getSex().getName()); em.getTransaction().commit(); em.close(); factory.close(); }
这里我们EntityManagerFactory就相当于Hibernate中的SessionFactory,
然而EntityManager就相当于Hibernate中的Session。
在JPA中我们获得它的方式是Persistence.createEntityManagerFactory("jun");
jun是在persistence.xml中持久化单元名称
EntityManager em = factory.createEntityManager();
其中EntityManager中的几种操作数据库方法有
Persist(),find(),getReference(),merge(),remove()这里我就列出几种常见的
这里说有的getReference()就相当于Hibernate中的Load() 支持Lazy加载,
getReference它会查找一个代理对象,当访问它的属性的时候它才会向数据库操作
但是值得注意的这个必须确保Session是打开状态
实体bean的几种状态 一、新建状态new一个实体的时候它所处于的状态
二、托管状态这个状态非常重要,当一个实体bean是托管状态的时候我们修改它的属性值得话,即使我们没有用到hibernate中的相关方法操作数据库,她也会同步到数据库里的,托管就是从数据库里面查询到的一个对象,记住,托管状态必须的和事物关联上来
em.getTransaction().begin(); person.setName("小刘"); em.getTransaction().commit(); em.close(); factory.close();三、游离状态
当我们使用EntityManager中的clear()方法的时候,它会把事物管理器中的所有实体变成游离状态,
处在游离状态的实体bean,我们修改它的属性它不会同步到数据库中的
em.getTransaction().begin(); em.clear(); // 把实体管理器中的所有实体都变成游离状态 person.setName("老刘"); em.merge(person); em.getTransaction().commit(); em.close(); factory.close();四、关闭状态
就是当我们把Session关闭的时候,实体bean处于的状态
JPA中使用EJQL语句 查询public void query() { /** * jun是在persistence.xml中持久化单元名称 */ EntityManagerFactory factory=Persistence.createEntityManagerFactory("jun"); //--->>SessionFactory-->>session-->>begin EntityManager em = factory.createEntityManager(); Query query = em.createQuery("select o from Person o where o.id=?1"); query.setParameter(1, 2); // /** * Person person = (Person)query.getSingleResult(); * 这个就相当于Hibernate中的uniqueResult(); * 如果没有查询到数据的话会出错的,所有我们一般不这样做 * 我们先得到List 然后遍历它 */ List删除查询(记得要开启事物)list = query.getResultList(); for(Person person : list) System.out.println("---------->>" + person.getName()); query = em.createQuery("select count(o) from Person o "); Long count = (Long)query.getSingleResult(); System.out.println("---------->>" + count); em.close(); factory.close(); }
public void deletequery() { /** * jun是在persistence.xml中持久化单元名称 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Query query = em.createQuery("delete from Person o where o.id=?1"); query.setParameter(1, 2); query.executeUpdate(); em.getTransaction().commit(); em.close(); factory.close(); }修改查询(记得要开启事物)
public void updatequery() { /** * jun是在persistence.xml中持久化单元名称 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Query query = em.createQuery("update from Person o set o.name=:name where o.id=:id"); query.setParameter("name", "小刘"); query.setParameter("id", 3); query.executeUpdate(); em.getTransaction().commit(); em.close(); factory.close(); }刷新方法
public void testgetPerson() { /** * jun是在persistence.xml中持久化单元名称 */ EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); //--->>SessionFactory-->>session-->>begin EntityManager em = factory.createEntityManager(); Person person = em.find(Person.class, 1); /** * 1分钟内 * 比方说这里有人直接操作数据库改了数据,我们如何来得到person呢 * 有人说我们可以再执行一下find方法,这个事不可以的,因为你再次 * 执行find方法的时候EntityManager会中一级缓存中取得id是1的 * Person数据,也就是说不能得到最新的数据,那么如果我们想得到最 * 新的数据怎么办呢?JPA帮我们做了一个刷新的方法em.refresh(person); * 通过它我们就可以得到最新的数据了 */ em.refresh(person); System.out.println("----->>"+person.getName()); em.close(); factory.close(); }JPA中实现表间关联关系 一的多
@Entity @Table(name="t_order") public class Order { @Id @Column(length=200) private String orderid; @Column(nullable=false) private Float amount = 0f; /** * cascade=CascadeType.REFRESH设置级联刷新 * CascadeType.PERSIST设置级联保存 * CascadeType.MERGE设置级联更新 * CascadeType.REMOVE设置级联删除 * CascadeType.ALL设置四种级联 * 这四种级联都是对应的四种方法才能起作用PERSIST(),MERGE(),REMOVE(),REFRESH() * fetch=FetchType.LAZY支持LAzy加载,只有用到该属性的时候才会读集合数据 * 注意这时我们必须保持EntityManager是开着的,默认是延迟加载 * mappedBy="order"指定OrderItem类里面的order这个属性来维护关系 */ @OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.LAZY, mappedBy="order") private Setitems = new HashSet (); // get set // }
为了我们添加Set集合方便我们通常的情况下我们的写一个添加Set的方法
public void addOrderItem(OrderItem orderItem) { orderItem.setOrder(this);//this就是Order items.add(orderItem); }多的一
@Entity @Table(name="t_orderitem") public class OrderItem { @Id @GeneratedValue private Integer id; @Column(length=40,nullable=false) private String productName; @Column(nullable=false) private Float sellPrice = 0f; /** * optional=false指定该字段不能空 * @JoinColumn(name="order_id")指明关联关系的子段名 * 即定义外键的名称 * * */ @ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},optional=false) @JoinColumn(name="order_id") private Order order; // get set // }测试
public void testCreate() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Order order = new Order(); order.setAmount(598f); order.setOrderid(UUID.randomUUID().toString()); OrderItem orderItem1 = new OrderItem(); orderItem1.setProductName("篮球"); orderItem1.setSellPrice(256f); order.addOrderItem(orderItem1); OrderItem orderItem2 = new OrderItem(); orderItem2.setProductName("女人"); orderItem2.setSellPrice(800000f); order.addOrderItem(orderItem2); em.persist(order); em.getTransaction().commit(); em.close(); factory.close(); }
这里我们并没有保存orderIterm
但是我们在数据库中依然能看到orderIterm的数据
保存到数据库里面了,这里就是设置级联保存的缘故
CascadeType.PERSIST设置级联保存
Person.java
@Entity @Table(name="t_person") public class Person { @Id @GeneratedValue private Integer id; @Column(length=10,nullable=false) private String name; @OneToOne(optional=false,cascade={CascadeType.ALL}) @JoinColumn(name="idcard_id") private IDCard idCard; public Person() {} public Person(String name) { this.name = name; } }
IDCard.java
@Entity @Table(name="t_idcard") public class IDCard { @Id @GeneratedValue private Integer id; @Column(length=18,nullable=false) private String cardno ; @OneToOne(mappedBy="idCard", cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE}) private Person person; public IDCard() {} public IDCard(String cardno) { this.cardno = cardno; } }测试
public void testCreateTable() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Person person = new Person("小刘"); IDCard idCard = new IDCard("411521198409131915"); idCard.setPerson(person); person.setIdCard(idCard); em.persist(person); em.getTransaction().commit(); em.close(); factory.close(); }多对多
Student.java
@Entity @Table(name="t_student") public class Student { @Id @GeneratedValue private Integer id; @Column(length=10,nullable=false) private String name; /** * @JoinTable(name="t_stu_tea", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="teacher_id")) 创建中间表来维护两个表的关系 * joinColumns=@JoinColumn(name="student_id")定义维护端在中间表中的关联字段 * inverseJoinColumns=@JoinColumn(name="teacher_id")定义被维护端在中间表中的关联字段 * */ @ManyToMany(cascade=CascadeType.REFRESH) @JoinTable(name="t_stu_tea", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="teacher_id")) private Setteachers = new HashSet (); public Student() {} public Student(String name) { this.name = name; } }
我们通常把set集合方法重写
public void addTeacher(Teacher teacher) { this.teachers.add(teacher); } public void removeTeacher(Teacher teacher) { if(this.teachers.contains(teacher)) { this.teachers.remove(teacher); } }
Teacher.java
@Entity @Table(name="t_teacher") public class Teacher { @Id @GeneratedValue private Integer id; @Column(length=12,nullable=false) private String name; @ManyToMany(cascade=CascadeType.REFRESH,mappedBy="teachers") private Set测试students = new HashSet (); public Teacher() {} public Teacher(String name) { this.name = name; } }
@Test public void testCreateTable() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = new Student("小刘"); Teacher teacher = new Teacher("肖老师"); em.persist(student); em.persist(teacher); em.getTransaction().commit(); em.close(); factory.close(); } /** * 建立学生跟老师的关系 */ @Test public void buildTS() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.find(Student.class, 1); student.addTeacher(em.getReference(Teacher.class, 1)); em.getTransaction().commit(); em.close(); factory.close(); } /** * 解除学生跟老师的关系 */ @Test public void deleteTS() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.find(Student.class, 1); student.removeTeacher(em.getReference(Teacher.class, 1)); em.getTransaction().commit(); em.close(); factory.close(); } /** * 删除老师 */ @Test public void deleteTeacher() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); /** * 删除老师的时候一定的解除掉老师和学生的关系 */ Student student = em.find(Student.class, 1); student.removeTeacher(em.getReference(Teacher.class, 1)); em.remove(em.getReference(Teacher.class, 1)); em.getTransaction().commit(); em.close(); factory.close(); } /** *删除学生 */ @Test public void deleteStudent() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); /** * 这个为什么不需要解除关系呢,主要是因为学生这一段是维护端 */ Student student = em.find(Student.class, 1); em.remove(student); em.getTransaction().commit(); em.close(); factory.close(); }联合主键
我们多带带写一个类作为主键,但是这个类的要满足3条规则
它必须实现Serializable接口
它必须重写字段的hashCode()和equals()方法
要在类上表明@Embeddable,这个注解的意思就是让它的属性在AirLine也正常做属性
那么我们在主体类里面用这个主键类做为id,在id上面加上@EmbeddedId表明就是用主键类的属性作为主键,并映射到数据库表中
AirLine.java
@Entity @Table(name="t_airline") public class AirLine { @EmbeddedId private AirLinePK id; @Column(length=10,nullable=false) private String name; }
AirLinePK.java
@Embeddable public class AirLinePK implements Serializable{ // 序列UID private static final long serialVersionUID = -7125628704970675246L; @Column(length=20) private String startLine; @Column(length=20) private String endLine; // 注意这里一定的时间他HashCode()和equals()方法 }测试
public void testPK() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jun"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); AirLine airLine = new AirLine("PEK","SHG","北京飞往上海"); em.persist(airLine); em.getTransaction().commit(); em.close(); factory.close(); }使用Spring Boot 配置
使用步骤类似上面介绍,关键是要理解一对一、一对多、多对一、多对多的关联关系
引入jpa yml文件org.springframework.boot spring-boot-starter-data-jpa
# maven打包 clean compile package spring: # 热重启 devtools: restart: enabled: true # 数据源 datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///qnzf?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false username: root password: # JPA配置 jpa: show-sql: true hibernate: naming: physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl ddl-auto: update # tomcat server: port: 8080 tomcat: Uri-encoding: UTF-8实体类映射数据表
LED.java
@Entity @Table(name = "tbl_led") public class LED { public LED() { super(); } // 指定id @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 唯一键 @Column(unique = true) private Integer pin; // LED连接的针脚位 // 单向一对一 @OneToOne() @JoinColumn(name = "ledtype_id") private LEDType ledType; }使用jpa接口方法
LEDRepository.java
public interface LEDRepository extends JpaRepositorymvc中使用{ }
@Autowired private LEDPowerRepository ledPowerRepository;个别使用方法可以浏览其他教程介绍加强一下
Spring For All 社区 Spring Data JPA 从入门到进阶系列教程
SpringBoot实战SpringDataJPA
使用 Spring Data JPA 简化 JPA 开发
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71560.html
摘要:一从零搭建环境本次我使用的是编辑器来搭建和环境首先,我们在新建项目的时候,选择,然后就行了。可以看出,本次的版本为。这是一个非常好用的插件,有了它我们可以不用写繁琐的方法。非常适合我们做一些简答的测试和小功能。 前言 只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 不知道大家对SpringB...
阅读 821·2023-04-26 00:37
阅读 706·2021-11-24 09:39
阅读 2132·2021-11-23 09:51
阅读 3767·2021-11-22 15:24
阅读 733·2021-10-19 11:46
阅读 1868·2019-08-30 13:53
阅读 2409·2019-08-29 17:28
阅读 1314·2019-08-29 14:11