Spring data & JPA learning notes

Posted by Aliz on Tue, 18 Jan 2022 22:52:29 +0100

jpa:Java Persistence api is a specification, and hibernate is its implementation.
jpql/hql: query language. jpql is a subset of hql.
1. Basic usage and annotation explanation
@MappedSuperclass
1. The class marked @ MappedSuperclass will not be a complete entity class. It will not be mapped to the database table, but its properties will be mapped to the database fields of its subclasses.
2. The class labeled @ MappedSuperclass cannot be annotated with @ Entity or @ Table annotation, and there is no need to implement the serialization interface.

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {
    @Getter
    @Setter
    @CreatedDate
    @Column(columnDefinition="datetime not null comment 'Creation time'")
    private LocalDateTime createdAt;
    @Getter
    @Setter
    @LastModifiedDate
    @Column(columnDefinition="datetime not null comment 'Update time'")
    private LocalDateTime modifiedAt;
}

@The EntityListeners(AuditingEntityListener.class) annotation is used to listen for the status of entity classes after save and update.
Remember to add @ EnableJpaAuditing to the Application startup class, otherwise @ CreatedDate, @ CreatedBy, @ LastModifiedDate, @ LastModifiedBy will not take effect.
However, CreatedBy and LastModifiedBy have no assignment, because you need to implement the AuditorAware interface to return the value you need to insert.

@Configuration
public class UserAuditorConfig implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        //Code for obtaining user information is omitted
        return Optional.of(SpringSecurityHolder.currentUserName());
    }
}

Table configuration

@Entity
@Table(name = "t_customer")
@org.hibernate.annotations.Table(appliesTo = "t_customer", comment = "Customer table")
@Getter
@Setter
public class Customer extends BaseEntity implements Serializable {
    //@TableGenerator() configures table to generate primary key, @ SequenceGenerator(). Learn Baidu yourself.
    @GeneratedValue(strategy = GenerationType.IDENTITY) //Primary key auto increment
    @Id
    @Column(columnDefinition="bigint unsigned COMMENT 'Primary key'")//Column definition
    private Long id;

    @Column(columnDefinition="varchar(32) COMMENT 'name'")
    private String lastName;

    @Column(columnDefinition="int COMMENT 'Age'")
    private Integer age;
}

@Basic annotations are available by default. fetch loading policy and optional are allowed to be empty.
@Transient is not used by table fields.
@Tempora(TemporalType.TIMESTAMP) is used in the attribute of Date type to specify the Date format (with or without hours, minutes and seconds).

Table generate primary key policy (understand)

CREATE TABLE `id_generators` (
  `id` int(10) NOT NULL,
  `pk_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `pk_value` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `jpa`.`id_generators`(`id`, `pk_name`, `pk_value`) VALUES (1, 'customer_id', 1);
@TableGenerator(name = "id_generator",
        table = "id_generators",//Table generating primary key
        pkColumnName = "pk_name",
        pkColumnValue = "customer_id",
        valueColumnName = "pk_value",
        allocationSize = 1)//allocationSize indicates the size of each increase in the primary key value
@GeneratedValue(strategy = GenerationType.TABLE, generator = "id_generator")
@Id
@Column(columnDefinition = "bigint unsigned COMMENT 'Primary key'")
private Long id;

Table relation

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {

}
@Repository
public interface OrderRepository extends JpaRepository<Order, Long>, JpaSpecificationExecutor<Order> {

}

Unidirectional many to one

@Entity
@Table(name = "t_order")
@org.hibernate.annotations.Table(appliesTo = "t_order", comment = "Order form")
@Getter
@Setter
public class Order extends BaseEntity implements Serializable {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(columnDefinition="bigint unsigned COMMENT 'Primary key'")
    private Long id;

    @Column(columnDefinition="varchar(32) COMMENT 'Order name'")
    private String orderName;

    /**
     * The many to one foreignKey configuration does not generate foreign keys
     */
    @ManyToOne
    @JoinColumn(name = "customer_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
    private Customer customer;
}
Be sure to save one end first,Save the other end,Otherwise, multiple updates will occur sql sentence. fetch Configure lazy loading.
When deleting,The party deleting one will report an error. Because there are foreign key constraints. select @@foreign_key_checks;

Be sure to save one end of a file first, otherwise an error may be reported
Unidirectional pair n

@Entity
@Table(name = "t_order")
@org.hibernate.annotations.Table(appliesTo = "t_order", comment = "Order form")
@Date
public class Order extends BaseEntity implements Serializable {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(columnDefinition="bigint unsigned COMMENT 'Primary key'")
    private Long id;

    @Column(columnDefinition="varchar(32) COMMENT 'Order name'")
    private String orderName;
}

@Entity
@Table(name = "t_customer")
@org.hibernate.annotations.Table(appliesTo = "t_customer", comment = "customer")
@Getter
@Setter
public class Customer extends BaseEntity implements Serializable {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(columnDefinition = "bigint unsigned COMMENT 'Primary key'")
    private Long id;

    @Column(columnDefinition = "varchar(32) COMMENT 'name'")
    private String lastName;

    @Column(columnDefinition = "int COMMENT 'Age'")
    private Integer age;
    /**
     * When one-way 1-n saves, there must be more update statements, because when n saves, foreign keys will not be inserted
     * The default lazy loading mode, and the fetch property in OneToMany is modified
     * When deleting, if one end of a customer is deleted, the customer in the customer (multiple party) table will be empty_ ID, delete again.
     * Configure cascade delete @ OneToMany(cascade = {CascadeType.REMOVE})
     */
    @OneToMany(cascade = {CascadeType.REMOVE})
    @JoinColumn(name = "customer_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
    private Set<Order> orders;
    //Remember to use idea to generate equals hashcode toString, which does not contain the orders field.
}

Bidirectional 1-n

@Entity
@Table(name = "t_order")
@org.hibernate.annotations.Table(appliesTo = "t_order", comment = "Order form")
@Getter
@Setter
public class Order extends BaseEntity implements Serializable {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(columnDefinition = "bigint unsigned COMMENT 'Primary key'")
    private Long id;

    @Column(columnDefinition = "varchar(32) COMMENT 'Order name'")
    private String orderName;

    @ManyToOne
    @JoinColumn(name = "customer_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
    private Customer customer;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Order order = (Order) o;
        return Objects.equals(id, order.id) && Objects.equals(orderName, order.orderName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, orderName);
    }
}

@Entity
@Table(name = "t_customer")
@org.hibernate.annotations.Table(appliesTo = "t_customer", comment = "customer")
@Getter
@Setter
public class Customer extends BaseEntity implements Serializable {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(columnDefinition = "bigint unsigned COMMENT 'Primary key'")
    private Long id;

    @Column(columnDefinition = "varchar(32) COMMENT 'name'")
    private String lastName;

    @Column(columnDefinition = "int COMMENT 'Age'")
    private Integer age;

    /**
     * mappedBy The association relationship is maintained by multiple parties, and mappedBy configures customer maintenance
     * OneToMany If mappedBy is configured, @ JoinColum cannot be configured. Note that the order table will generate foreign keys at this time
     */
    @OneToMany(cascade = {CascadeType.REMOVE}, mappedBy = "customer")
    private Set<Order> orders;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Customer customer = (Customer) o;
        return Objects.equals(id, customer.id) && Objects.equals(lastName, customer.lastName) && Objects.equals(age, customer.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, lastName, age);
    }
}

object references an unsaved transient instance - save the transient instance before flushing... Is normal
Configurable cascade = cascadetype Persist, self Baidu
Two way one-to-one

Table inheritance

2. Common methods
Four states of Hibernate entity objects
Transient (temporary): objects created by the new operator and not yet associated with Hibernate Session are considered transient. Transient objects are not persisted to the database and are not given a persistent identity.
Persistent state: a persistent instance may be just saved or just loaded. It exists within the scope of the associated Session. When flushing () caches or commits a transaction, the database is automatically updated according to changes in object properties.
Free state (managed state): there is a persistent primary key. After the Session associated with the persistent object is closed, the object becomes unmanaged. The off tube state cannot be persisted directly.
Delete status: after calling the delete method of Session, the object becomes deleted. It has a persistent primary key, but it is deleted from the database.

jap

obtain EntityManager object
@Resource
private EntityManagerFactory entityManagerFactory;
//sessionFactory similar to hibernate
EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//Processing business code
transaction.commit();
entityManager.close();
//The find method is similar to the get method of Session in hibernate
Customer employee = entityManager.find(Customer.class, 1);
//The getReference method is similar to the load method of hibernate Session, lazy loading. Query when using objects.
//If the transaction is committed before use and the entityManager is closed, there will be an exception.
Customer reference = entityManager.getReference(Customer.class, 1);
//Persistent persistence is similar to the save method of hibernate Session. The free state of the object becomes persistent.
//The difference is that if the object has an id,persist throws an exception and cannot be inserted, and the save method does not.
entityManager.persist(employee);
//Remove is similar to the delete method of hibernate Session. The difference is that only persistent objects can be removed, while hibernate delete method can remove temporary objects.
Customer customer = entityManager.find(Customer.class, 3);
entityManager.remove(customer);
//merge is similar to the saveOrUpdate method of hibernate Session,
entityManager.merge(customer2);
Incoming temporary object,Copy temporary objects to new objects,Then persist the new object,only customer1 have id. 
Customer customer = new Customer();
customer.setLastName("Dance 3");
Customer customer1 = entityManager.merge(customer);
System.out.println("employee:" + customer.getId()); //No id
System.out.println("employee1:" + customer1.getId());//Have id
//Incoming free object (with primary key id)
//1. If neither the EntityManager cache nor the database has this object, copy the free object to the new object, and then persist the new object. customer id is 1000, and customer1 id is the real primary key id.
//2. If the EntityManager cache does not have this object and the database has this object, JPA queries the corresponding record and returns this record object 2. Copy the free object attribute to object 2, and object 2 executes update.
//3. If the EntityManager caches this object, JPA copies the free object attribute to the cache object and update s the cache object. hibernate does not satisfy the third point.

entityManager.flush();The data in memory is consistent with the database data
//You can issue sql statements (when the persistent object is modified), and the default flush is before the transaction is committed.
entityManager.refresh(customer);Retrieve the objects in the database
contains(Object entity):Judge whether an instance belongs to the entity managed by the current persistent context environment.
isOpen():Judge whether the current entity manager is open.
close():Close the entity manager.
//After closing, if the method of the entity manager instance or the method of its derived query object is called, an IllegalStateException will be thrown
//However, when the transaction associated with the entity manager is active, the persistent context will remain managed after using the close method until the transaction is completed.

hibernate

obtain SessionFactory
@Resource
private EntityManagerFactory entityManagerFactory;
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//Processing business code
transaction.commit();
session.close();
sessionFactory.close();

Topics: Java Hibernate jpa