Rumah  >  Artikel  >  Java  >  Cara menggunakan anotasi biasa SpringBoot JPA

Cara menggunakan anotasi biasa SpringBoot JPA

WBOY
WBOYke hadapan
2023-05-13 09:40:191140semak imbas

    1 Pengenalan

    Jpa ialah set spesifikasi ORM
    Bukankah hibernate hanya ORM rangka kerja? Menyediakan pelaksanaan JPA

    JPA (Java Persistence API): java persistence API

    2

    menandakan kelas semasa sebagai kelas entiti, yang akan dipetakan ke jadual pangkalan data yang ditentukan

    @Entity
    public class Users {
    		
    }

    2.2 @Jadual

    biasanya dianotasi bersama dengan

    @Entity

    Gunakan, jika nama jadual pangkalan data dan nama kelas adalah konsisten, tidak mengapa untuk tidak menggunakan anotasi @Table, jika tidak, anda perlu menggunakan @Table
    anotasi untuk menentukan nama jadual

    @Entity
    @Table(name="t_users")
    public class Users {
    		
    }
    2.3 @Id, @GeneratedValue, @SequenceGenerator, @Column

    2.3.1 @Id

    digunakan untuk memetakan atribut kelas entiti kepada kunci utama

    2.3.2 @ GeneratedValue

    Nyatakan strategi penjanaan kunci utama
    package javax.persistence;
    /**
     * 策略类型
     */
    public enum GenerationType {
      /**
       * 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植
       */
      TABLE,
      /**
       * 通过序列产生主键,通过 @SequenceGenerator 注解指定序列名
       * MySql 不支持这种方式
       * Oracle 支持
       */
      SEQUENCE,
      /**
       * 采用数据库 ID自增长的方式来自增主键字段
       * Oracle 不支持这种方式;
       */
      IDENTITY,
      /**
       * 缺省值,JPA 根据数据库自动选择
       */
      AUTO;
    
      private GenerationType() {
      }
    }

    2.3.3 @SequenceGenerator

    2.3.4 @Lajur
    Apabila nama atribut kelas entiti dan nama lajur pangkalan data tidak konsisten Anotasi ini mesti digunakan
    @Entity
    @Table(name="t_users")
    public class Users {
    
      @Id
      @Column(name = "user_id")
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
      @SequenceGenerator(name = "user_seq", sequenceName = "user_seq")
      private Long userId;
    		
    }

    2.4 @Transient

    menunjukkan bahawa atribut semasa tidak perlu dipetakan kepada pangkalan data

    2.5 @Temproal

    Terutama untuk penggunaan atribut jenis Tarikh, anda boleh menentukan ketepatan masa melalui anotasi ini

    @Entity
    @Table(name="t_users")
    public class Users {
    
      @Temporal(TemporalType.DATE) 
      private Date time1;
      
      @Temporal(TemporalType.TIME)
      private Date time2;
      
      @Temporal(TemporalType.TIMESTAMP)
      private Date time3;
    }

    3 🎜>

    serupa dengan SessionFactory hibernate

    4 jenis Status entiti EntityManager

    Status baharu:

    Ciptaan baharu belum lagi mempunyai kunci primer yang berterusan

    Status ketekunan:

    Sudah mempunyai kunci utama yang berterusan dan telah mewujudkan konteks dengan ketekunan Keadaan bebas: Mempunyai kunci primer yang berterusan, tetapi tidak mempunyai hubungan konteks dengan ketekunan Keadaan dipadamkan: Mempunyai kunci utama yang berterusan dan mempunyai hubungan konteks dengan ketekunan, tetapi telah dipadamkan daripada pangkalan data 4.1 find(Class entityClass, Object primaryKey)

    Serupa dengan get() sesi dalam hibernate

    find akan mengembalikan null jika ia tidak disoal

    4.2 getReference(Class entityClass, Object primaryKey)

    Serupa dengan load() sesi dalam hibernate

    Hanya apabila atribut dalam objek sebenarnya diperoleh, pertanyaan akan dilaksanakan pernyataan SQL, getReference() hanya mengembalikan objek proksi

    getReference tidak akan mengembalikan null jika ia tidak ditanya, dan akan membuang EntityNotFoundException

    4.3 berterusan

    注意:使用此方法可能出现懒加载异常的情况,也就是我们还没有去获取实体类中的属性值,结果 EntityManager 就已经被关闭了

    serupa dengan save()

    4.4 alih keluar

    注意:执行方法时传入的对象不能为主键设置值会抛出异常

    dalam hibernate Sama seperti delete()

    	/**
    	 * 删除游离态(失败)
    	 */
    	public void testRemove(){
    		Users user = new Users();
    		Users.setUserId(1);
    		entityManager.remove(customer);
    	}
    	
    	/**
    	 * 删除持久化状态(成功)
    	 */
    	public void testRemove(){
    		Users user = entityManager.find(Users.class, 1);
    		entityManager.remove(user);
    	}
    4.5 merge(T entiti)

    注意:该方法只能删除持久化对象,而不能删除游离状态的对象(hibernate 可以)

    dalam hibernate, serupa dengan saveOrUpdate( sesi dalam hibernate )

    	// 新建状态
    	public void testMerge	(){
    		Users user= new Users();
    		// 省略一系列的set
    		// user.set.....
    		Users newUser = entityManager.merge(user);
    		// user.getUserId() == null  ==> true
    		// newUser.getUserId() == null ==> false
    	}

    4.6 flush()

    Cara menggunakan anotasi biasa SpringBoot JPA

    adalah serupa dengan flush() sesi dalam hibernate

    Simpan semua entiti yang tidak disimpan dalam konteks ke pangkalan data

    4.6 refresh()

    Serupa dengan refresh() sesi dalam hibernate

    Muat semula nilai atribut semua entiti

    5 >

    EntityManager.getTransaction()

    5.1 bermula

    5.2 commit

    5.3 rollback

    6 🎜>

    6.1 Sehala satu-ke-banyak

    Ambil perhubungan antara pengguna dan pesanan sebagai contoh, pengguna Terdapat berbilang pesanan dan satu pesanan hanya dimiliki oleh seorang pengguna

    Untuk sisipan dalam hubungan satu-dengan-banyak, sama ada sisi banyak atau satu sisi dimasukkan dahulu, penyata kemas kini tambahan akan dijana, kerana sisi yang banyak tidak akan disisipkan semasa lajur kunci asing

    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_order")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    6.2 Sehala banyak-ke-satu


    Ambil perhubungan antara pengguna dan pesanan sebagai contoh Seorang pengguna mempunyai berbilang pesanan dan pesanan hanya Milik satu pengguna

    Untuk sisipan dalam perhubungan banyak dengan satu, sebaiknya simpan satu hujung dahulu dan kemudian simpan hujung yang banyak.
    Jika anda menyimpan banyak hujung dahulu dan kemudian satu hujung, untuk mengekalkan hubungan kunci asing, anda perlu melakukan operasi kemas kini tambahan pada hujung banyak

    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_order")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }
    6.3 Dwiarah banyak- kepada-satu



    Ambil perhubungan antara pengguna dan pesanan sebagai contoh Seorang pengguna mempunyai berbilang pesanan, dan satu pesanan hanya dimiliki oleh seorang pengguna

    Dua hala many-to-one ialah satu. gabungan dua di atas, menggunakan @OneToMany dan @ManyToOne

    /**
     * 用户和订单是一对多的关系
     */
    @Entity
    @Table(name="t_users")
    public class User {
    	// 如果两侧都要描述关联关系的话,维护关联关系的任务要交给多的一方
    	// 使用 @OneToMany 了 mappedBy 的代表不维护关联关系,也就是不会产生额外的update语句
    	// @OneToMany 和 @JoinColumn 不能同时使用会报错
    	@OneToMany(mappedBy="user")
    	private Set<Orders> orders;
    }
    
    /**
     * 订单和用户是多对一的关系
     */
    @Entity
    @Table(name="t_orders")
    public class Order {
    	// lazy为懒加载,默认为eager立即查询
    	@ManyToOne(fetch=FetchType.Lazy)
    	// @JoinColumn标注字段是一个类,userId为该类的主键
    	@JoinColumn(name="user_id")
    	private Users user;
    }

    6.4 双向一对一

    以学校和校长之间的关系为例,一个学校只有一个校长,一个校长也只属于一个学校
    一方使用 @OneToMany + @JoinColumn,另一方使用 @OneToOne(mappedBy=“xx”)
    具体由哪一方维护关联关系都可以,这里我们以学校一端维护关联关系为例
    保存时先保存不维护关联关系的一方(也就是使用@OneToOne(mappedBy=“xx”)的一方),否则会产生额外的 update 语句

    /**
     * 学校
     */
    @Entity
    @Table(name="t_school")
    public class School {
    	// 默认为eager立即查询
    	@OneToOne
    	// 添加唯一约束
    	@JoinColumn(name="school_master_id", unique = true)
    	private SchoolMaster schoolMaster;
    }
    
    /**
     * 校长
     */
    @Entity
    @Table(name="t_school_master")
    public class SchoolMaster {
    	// 不维护关联关系要使用 mappedBy
    	@OneToOne(mappedBy="schoolMaster")
    	private School school;
    }

    6.5 双向多对多

    以学生和课程之间的关系为例,一个学生可以选多门课,一个课程也有多个学生,多对多需要一个中间表,也就是选课表
    维护关联关系的一方需要使用 @JoinTable
    关联关系也是只有一方维护即可,这里我们由学生表进行维护

    /**
     * 学生
     */
    @Entity
    @Table(name="t_student")
    public class Student {
    	@GeneratedValue
    	@Id
    	private Long student_id;
    	
    	// 要使用 set 集合接收
    	// 默认为lazy懒加载
    	@ManyToMany
    	// name 为中间表的表名
    	@JoinTable(name="t_student_choose_course",
    			// name 为与中间表与当前表所关联的字段的名称,referencedColumnName 为当前表中与中间表关联的字段的名称
    			joinColumns={@JoinColumn(name="student_id", referencedColumnName="student_id")},
    			// name 为与中间表与多对多另一方表所关联的字段的名称,referencedColumnName 为多对多另一方与中间表关联的字段的名称
    			inverseJoinColumns={@JoinColumn(name="course_id", referencedColumnName="course_id")})
    	private Set<Course> courses;
    }
    
    /**
     * 课程
     */
    @Entity
    @Table(name="t_course")
    public class Course {
    	@GeneratedValue
    	@Id
    	private Long course_id;
    	
    	// 要使用 set 集合接收
    	// 默认为lazy懒加载
    	@ManyToMany(mappedBy="courses")
    	private Set<Student> students;
    }

    7. 二级缓存

    开启了二级缓存之后,缓存是可以跨越 EntityManager 的,
    默认是一级缓存也就是在一个 EntityManager 中是有缓存的
    二级缓存可以实现,关闭了 EntityManager 之后缓存不会被清除
    使用 @Cacheable(true) 开启二级缓存

    8. JPQL

    8.1 查询接口

    8.1.1 createQuery
    	public void testCreateQuery(){
    		// 这里我们使用了一个 new Student,因为我们是查询 Student 中的部分属性,如果不适用 new Student 查询返回的结果就不是 Student 类型而是一个 Object[] 类型的 List
    		// 也可以在实体类中创建对应的构造器,然后使用如下这种 new Student 的方式,来把返回结果封装为Student 对象
    		String jpql = "SELECT new Student(s.name, s.age) FROM t_student s WHERE s.student_id > ?";
    		// setParameter 时下标是从1开始的
    		List result = entityManager.createQuery(jpql).setParameter(1, 1).getResultList();
    	}
    8.1.2 createNamedQuery

    需要在类上使用 @NamedQuery 注解,事先声明 sql 语句

    @NamedQuery(name="testNamedQuery", query="select * from t_student WHERE student_id = ?")
    @Entity
    @Table(name="t_student")
    public class Student {
    	@GeneratedValue
    	@Id
    	private Long student_id;
    	
    	@Column
    	private String name;
    	
    	@Column
    	private int age;
    }
    	public void testCreateNamedQuery(){
    		Query query = entityManager.createNamedQuery("testNamedQuery").setParameter(1, 3);
    		Student student = (Student) query.getSingleResult();
    	}
    8.1.3 createNativeQuery
    	public void testCreateNativeQuery(){
    		// 本地sql的意思是只能在数据库中执行的sql语句
    		String sql = "SELECT age FROM t_student WHERE student_id = ?";
    		Query query = entityManager.createNativeQuery(sql).setParameter(1, 18);
    		Object result = query.getSingleResult();
    	}

    8.2 关联查询

    存在一对多关系时,当我们查询一的一端时,默认多的一端是懒加载。此时我们如果想要一次性查询出所有的数据就需要使用关联查询

    注意: 下面 sql 中的重点就是要加上 fetch u.orders,表示要查询出用户所关联的所有订单

    	public void testLeftOuterJoinFetch(){
    		String jpql = "FROM t_users u LEFT OUTER JOIN FETCH u.orders WHERE u.id = ?";
    		
    		Users user = (Users) entityManager.createQuery(jpql).setParameter(1, 123).getSingleResult();
    	}

    Atas ialah kandungan terperinci Cara menggunakan anotasi biasa SpringBoot JPA. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam