Spring in action reading notes (nine) Spring and Java Persistence API (JPA)

Java Persistence API, the Java Persistence API (JPA), using object - relational mapping persistent data.

One: Configure EntityManager

EntityManage is an interface that defines add, delete, change, some of the basic operations of the search, is created by EntityManagerFactory, according EntityManagerFactory create and manage different ways, can be divided into two categories:

(1) Application Management Type: PersistenceProvider method createEntityManagerFactory create EntityManagerFactory

(2) container management types: PersistenceProvider method createContainerEntityManagerFactory create EntityManagerFactory

Spring in the Find entityManagerFactory instance (? This place did not understand), will look to AbstractEntityManagerFactoryBean class, afterPropertiesSet method to create EntityManagerFactory instance, its agents, create EntityManagerFactory way createNativeEntityManagerFactory abstract method LocalContainerEntityManagerFactoryBean AbstractEntityManagerFactoryBean two subclasses in class , the LocalEntityManagerFactoryBean achieved, and thus the configuration LocalContainerEntityManagerFactoryBean LocalEntityManagerFactoryBean the bean implementation, can be arranged EntityManagerFactory.

1, the configuration of the JPA application management type (not implemented)

2, the configuration management type container JPA

Configuration by LocalContainerEntityManagerFactoryBean (mysql database used in the present embodiment)

package test.config;
import org.apache.commons.dbcp2.BasicDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import javax.sql.DataSource; @Configurationpublic class JpaConfiguration { @Bean public JpaTransactionManager transactionManager() { return new JpaTransactionManager(); } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource); emf.setJpaVendorAdapter(jpaVendorAdapter); emf.setPackagesToScan("test"); return emf; } }

JpaVendorAdapter DataSource and parameter settings should be mapped to the database.

Wherein DataSource is commons-dbcp2-2.5.0.jar package DataSource implementation: BasicDataSource, configure the user name, password, url. driver, etc.

    @Bean
    public DataSource dateSource() throws Exception {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriver(new com.mysql.cj.jdbc.Driver());
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test?userUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dataSource.setUsername("root");
        dataSource.setPassword("admin");
        datasource.setınitialsiz to ( 5 );
        dataSource.setMaxTotal(10);
        return dataSource;
    }
JpaVendorAdapter achieve a variety of choice here HibernateJpaVendorAdapter
    @Bean
    public HibernateJpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setDatabase(Database.MYSQL);
        adapter.setShowSql(true);
        adapter.setGenerateDdl(true);
        adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
        return adapter;
    }

Two: writing JPA-based Repository

Or may be injected EntityManager EntityManagerFactory example, a database operation.

Suppose database category_, the corresponding class Category, the annotation of the field

package test;

import javax.persistence.*;


@Entity
@Table(name = "category_")
public class Category {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private int id;

    @Column(name="name")
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Category{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

junit tests are as follows:

package test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import test.config.JpaConfiguration;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {JpaConfiguration.class})
public class EntityManagerFactoryTest {

    @PersistenceUnit
    private EntityManagerFactory emf;

    @PersistenceContext
    private EntityManager em;

    @Test
    public void test() {
        Category category = emf.createEntityManager().find(Category.class, 52);
        System.out.println(category);

        category = em.find(Category.class, 52);
        System.out.println(category);
    }
}

When injected EntityMangerFactory by @PersistenceUnit notes, each operation will create a database EntityManager, and EntityManager is not thread-safe, will cause the thread safety issues;

EntityManager is injected through @PersistenceContext notes, in fact injected EntityManager of a proxy, if the current transaction has no corresponding EntityManager agency will create a new one.

Three: With Spring Data JPA Repository automate

By way of the interface, create Repository

package test;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CategoryRepository extends JpaRepository<Category, Long> {
    
}

Injection CategoryRepository object, you can use the Save Repository interface defined, delete, query methods based on the id.

配置 Spring Data JPA:

Increase @EnableJpaRepositories (basePackages = "test") annotation on JPAconfiguration class (basePackages specified scanning package)

1, the definition of query method

Query methods defined rules are as follows:

Query results verb + restriction conditions, which can query the verb to get, read, find and count, get, read, find returns the number of objects, and count returns a match object.

For example readByName (String name) looks based on the name property.

readByNameIgnoringCase (String name): Ignore the name case

Specific query methods defined << Spring in action4 >> 11.3.1 section

2, Statement Custom Query

If the method is difficult to express the expected naming convention, such as a query select c from category_ c where c.name like corresponding to the results of the statement 'A% a',

@Query may be used in the following query CategoryRepository annotation method defined (corresponding to the Category class name, not the name of the database table)

@Query("select c from Category c where c.name like 'A%a'")
List<Category> findAllStartsWithA();

This method can be used after the injection CategoryRepository method.

3, mixing custom functionality

Spring Data JPA interfaces to achieve generated when the interface looks the same name and add a class Impl suffix. If the class exists, Spring Data JPA manner it will Spring Data JPA generated combined method.

If the method or use @Query naming convention can not achieve the desired method of CategoryRepository interfaces, the method may be implemented in custom CategoryRepositoryImpl class defines an interface method

public interface CategoryUpdate {
    int updateCategory();
}

CategoryRepositoryImpl implement the interface in

package test;


import org.springframework.data.jpa.repository.Modifying;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class CategoryRepositoryImpl implements CategoryUpdate {

    @PersistenceContext
    private EntityManager em;


    public  int UpdateCategory () {
         // here written statement to be executed 
        String SQL = "Update the Category C = SET c.NAME 'Aa' = WHERE c.NAME 'AA'" ;
         return em.createQuery (SQL) .executeUpdate ( );
    }
}

Modify CategoryRepository, so that it inherits from CategoryUpdate 

package test;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

public interface CategoryRepository extends JpaRepository<Category, Long>, CategoryUpdate {

    Category findByName(String name);

    @Query("select c from Category c where c.name like 'A%'")
    List<Category> findAllStartsWithA();
}

junit test:

 
 
@Autowired
private CategoryRepository categoryRepository;
@Test
@Modifying
@Transactional
@Rollback(false)
public void test3() {
    categoryRepository.updateCategory();
}

@EnableJpaRepositories repositoryImplementationPostfix can specify the name attribute set CategoryRepository interface implementation class, which is the default Impl.

Download Project

Guess you like

Origin www.cnblogs.com/wushengwuxi/p/12164443.html