spring data jpa use (1)

spring data jpa
A subproject of Spring. Used to simplify database access, support NoSQL and relational data storage. Its main goal is to make database access convenient and fast.
Dedicated to reducing the amount of data access layer (DAO) development. The only thing developers need to do is declare the persistence layer interface, and the rest is handed over to Spring Data JPA to help you complete.

The first spring data jpa program

1. Create projects and import required jar packages

2. Introduce spring configuration file (application Context. xml) and database connection configuration file (db.properties).
In db.properties:

jdbc.user=root
jdbc.password=123456
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///spring-data-jpa

In applicationContext.xml:

<!-- 1.To configure c3p0 data source -->
    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="driverClass" value="${jdbc.driverClass}"/>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
    </bean>

    <!-- 2.To configure EntityManagerFactory -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- To configure JPA Provider's adapter ,It can be done internally. bean How to configure-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
        </property>
        <!-- Configure the package where the entity class is located -->
        <property name="packagesToScan" value="com.itheima.entity"></property>
        <!-- To configure jpa Basic attributes.for example JPA Implementing product attributes -->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>
    <!-- 3.To configure jpa Transaction Manager Used -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!-- 4.Configuration support annotation-based transaction approach -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- Configuring Packages for Automatic Scanning -->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!-- To configure spring data -->
    <!-- join jpa Namespace -->
    <!-- 
        base-package: Used for scanning Repository Bean Where package
     -->
    <jpa:repositories base-package="com.itheima" entity-manager-factory-ref="entityManagerFactory"/>

Add entity classes: User

@Entity
@Table(name = "t_user")
public class User {

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

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

    private String password;

    private String telephone;

    private String email;

    @Column(name="create_time")
    private Date createTime;
    @Column(name="modified_time")
    private Date modifiedTime = new Date();

    //Mapping must define an empty constructor
    public User() {
    }

    public User(String userName, String password, String telephone, String email, Date createTime) {
        this.userName = userName;
        this.password = password;
        this.telephone = telephone;
        this.email = email;
        this.createTime = createTime;
    }
    get,set,toString Method
}

The database table is as follows:

3. Create User Repository Interface to Inherit Repository Interface

public interface UserRepository extends Repository<User, Long>{ 
    User findById(long id);
    User findByUserName(String username);
}

Repository interface is an identifier, and any interface that inherits this interface will be included in spring container management. findById (findByUserName) method, as its name implies, is based on id (user name) to query users. It's amazing that as long as it's written like this, we can actually find out the user's information according to id (username) without any processing. It's all because spring data standardizes our naming.

4, test

public class TestSpringDateJpa {

    ApplicationContext applicationContext ;
    @Before
    public void before(){
        applicationContext = 
                new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    }
    /*
     * findById()
     */
    @Test
    public void test1(){
        UserRepository userRepository = applicationContext.getBean(UserRepository.class);
        User user = userRepository.findById(1l);
        System.out.println(user);
    }
    /*
     * findByName()
     */
    @Test
    public void test2(){
        UserRepository userRepository = applicationContext.getBean(UserRepository.class);
        User user = userRepository.findByUserName("aaa");
        System.out.println(user);
    }
}

Result:

Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.create_time as create_t2_1_,
        user0_.email as email3_1_,
        user0_.modified_time as modified4_1_,
        user0_.password as password5_1_,
        user0_.telephone as telephon6_1_,
        user0_.user_name as user_nam7_1_ 
    from
        t_user user0_ 
    where
        user0_.id=?
User [id=1, userName=aa, password=123456, telephone=13344444445, email=aa@qq.com]

According to the output of user information inquired by id, we can see that the sql sent is inquiring user information according to ID.

Look at other query naming specifications:
(1)

    List<User> findByUserNameStartingWithAndIdLessThan(String username,long id);
    This method is equivalent to querying sql: WHERE user Name LIKE?% AND id<?

Test:

    /*
     * findByUserNameStartingWithAndIdLessThan();
     */
    @Test
    public void test3(){
        UserRepository userRepository = applicationContext.getBean(UserRepository.class);
        List<User> users = userRepository.findByUserNameStartingWithAndIdLessThan("aa", 3);
        for (User user : users) {
            System.out.println(user);
        }
    }

Result:

Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.create_time as create_t2_1_,
        user0_.email as email3_1_,
        user0_.modified_time as modified4_1_,
        user0_.password as password5_1_,
        user0_.telephone as telephon6_1_,
        user0_.user_name as user_nam7_1_ 
    from
        t_user user0_ 
    where
        (
            user0_.user_name like ?
        ) 
        and user0_.id<?
User [id=1, userName=aa, password=123456, telephone=13344444445, email=aa@qq.com]
User [id=2, userName=aaa, password=123456, telephone=15551182345, email=aaa@qq.com]

(2)

    List<User> getByTelephoneInOrIdGreaterThan(List<String> teles,long id);
    This method queries sql: WHERE telephone IN (?,???) OR ID <?

Test:

/*
     * getByTelephoneInOrIdGreaterThan();
     */
    @Test
    public void test4(){
        UserRepository userRepository = applicationContext.getBean(UserRepository.class);
        List<String> teles = new ArrayList<String>();
        teles.add("13344444445");
        teles.add("15551182345");
        long id = 5l;
        List<User> users = userRepository.getByTelephoneInOrIdGreaterThan(teles, id);
        for (User user : users) {
            System.out.println(user);
        }
    }

Result:

Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.create_time as create_t2_1_,
        user0_.email as email3_1_,
        user0_.modified_time as modified4_1_,
        user0_.password as password5_1_,
        user0_.telephone as telephon6_1_,
        user0_.user_name as user_nam7_1_ 
    from
        t_user user0_ 
    where
        user0_.telephone in (
            ? , ?
        ) 
        or user0_.id>?
User [id=1, userName=aa, password=123456, telephone=13344444445, email=aa@qq.com]
User [id=2, userName=aaa, password=123456, telephone=15551182345, email=aaa@qq.com]
User [id=6, userName=ccc, password=123456, telephone=13346789876, email=ccc@qq.com]

(3)

    List<User> getByEmailStartingWithOrderByIdDesc(String email);
    This method is equivalent to querying sql: WHERE email like?% ORDER BY ID DESC

Test:

/*
     * getByEmailStartingWithOrderByIdDesc();
     */
    @Test
    public void test5(){
        UserRepository userRepository = applicationContext.getBean(UserRepository.class);
        List<User> users = userRepository.getByEmailStartingWithOrderByIdDesc("aa");
        for (User user : users) {
            System.out.println(user);
        }
    }

Result:

Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.create_time as create_t2_1_,
        user0_.email as email3_1_,
        user0_.modified_time as modified4_1_,
        user0_.password as password5_1_,
        user0_.telephone as telephon6_1_,
        user0_.user_name as user_nam7_1_ 
    from
        t_user user0_ 
    where
        user0_.email like ? 
    order by
        user0_.id desc
User [id=2, userName=aaa, password=123456, telephone=15551182345, email=aaa@qq.com]
User [id=1, userName=aa, password=123456, telephone=13344444445, email=aa@qq.com]

Other keywords are also supported:

If you don't want to remember these, of course, they don't necessarily meet our query needs. We can write our own query conditions without paying attention to these keywords. The keywords are for convenience, but they can be completely used. At this time, we can use the annotation @Query provided by spring data.

@Query

@ Query allows us to write sql by hand, encapsulating query results into declared returned entity types based on the incoming parameters.

For example, query the user information with the largest id

@Query(value="SELECT u FROM User u WHERE u.id=(SELECT max(t.id) FROM User t)")
    User findUserWithMaxId();

Test:

    @Test
    public void test1(){
        UserRepository userRepository = applicationContext.getBean(UserRepository.class);
        User user = userRepository.findUserWithMaxId();
        System.out.println(user);
    }

Result:

Hibernate: 
    select
        user0_.id as id1_1_,
        user0_.create_time as create_t2_1_,
        user0_.email as email3_1_,
        user0_.modified_time as modified4_1_,
        user0_.password as password5_1_,
        user0_.telephone as telephon6_1_,
        user0_.user_name as user_nam7_1_ 
    from
        t_user user0_ 
    where
        user0_.id=(
            select
                max(user1_.id) 
            from
                t_user user1_
        )
User [id=6, userName=ccc, password=123456, telephone=13346789876, email=ccc@qq.com]

Note: The query statements here are object-oriented queries, which are unique jpql queries of jpa. JPA supports native sql queries, which are also supported here. It is recommended to use native sql queries when you are not familiar with jpql queries or more complex queries. Property needs to be set: nativeQuery=true

Using native sql queries
For example: query password, ask not to repeat

@Query(value="SELECT DISTINCT(password) FROM t_user",nativeQuery=true)
    String findPassword();

Test: slightly

Parameter passing
1. Use placeholders (recommended)

@Query(value="SELECT * FROM t_user u WHERE u.email LIKE ?1% AND id <?2",nativeQuery=true)
    List<User> findUserByemail(String email,long id);

Test:

    @Test
    public void test3(){
        UserRepository userRepository = applicationContext.getBean(UserRepository.class);
        List<User> list = userRepository.findUserByemail("aa", 2);
        for (User user : list) {
            System.out.println(user);
        }
    }

Result:

Hibernate: 
    SELECT
        * 
    FROM
        t_user u 
    WHERE
        u.email LIKE ? 
        AND id <?
User [id=1, userName=aa, password=123456, telephone=13344444445, email=aa@qq.com]

2. Naming with parameters

    @Query(value="SELECT * FROM t_user u WHERE u.email LIKE :userEmail% AND id <:userId",nativeQuery=true)
    List<User> findUserByemail2(@Param("userId")long id,@Param("userEmail")String email);

Test:

Hibernate: 
    SELECT
        * 
    FROM
        t_user u 
    WHERE
        u.email LIKE ? 
        AND id <?
User [id=1, userName=aa, password=123456, telephone=13344444445, email=aa@qq.com]

Although using parameter naming method does not need to regulate the order of multiple parameters, it is more troublesome, so placeholders are recommended.

DML operations using annotations
The previous @Query annotations are all query operations. If you want to update the data, you need to use them together with the annotation @Modifying. Note: Insert operations are not supported.

    @Modifying
    @Query(value="UPDATE t_user SET user_name = ?1 WHERE id=?2",nativeQuery=true)
    void updateUserNameById(String username,long id);

Spring Data provides the default transaction handling, that is, all queries are declared read-only transactions. Therefore, the operation of adding, deleting and modifying is not feasible. Usually, transactions are added to the Service layer in the three-tier architecture, so we can add a service, call Repository layer method in this layer, and add annotations (transactions can be read-write rather than just read-only transactions, for custom methods, if you need to change the default mode of transactions provided by Spring Data, you can annotate the @Transactional statement on the method) when testing. Service is called to modify the operation.

Service implementation class:

@Service(value=UserServiceImpl.SERVICE_NAME)
public class UserServiceImpl implements UserService{

    public static final String SERVICE_NAME="com.itheima.service.UserServiceImpl";
    @Autowired
    public UserRepository userRepository;
    @Transactional
    public void updateUser(String username, long id) {
        userRepository.updateUserNameById(username, id);
    }
}

Test:

    @Test
    public void test5(){//Must have @Transactional annotation
        UserService userService = applicationContext.getBean(UserService.class);
        userService.updateUser("Lucene", 1l);
    }

Result:

Hibernate: 
    UPDATE
        t_user 
    SET
        user_name = ? 
    WHERE
        id=?

View the user-selected username of the database t_user table id 1

Note: If it's useful in a project, it's probably the spring boot project, so you don't have to write that bunch of configuration files at this time. You just need to import the package (check it when you create the project, you don't need to import it manually, you need to install the STS plug-in with eclipse), and then configure it in the spring boot configuration file (application.properties), as follows:

spring.datasource.url=jdbc:mysql://localhost:3306/logistic
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql= true
spring.jpa.properties.hibernate.format_sql=true

Then start the project configuration and take effect, and then interact with the database.

Keywords: Spring Hibernate JDBC SQL

Added by kristy7 on Wed, 29 May 2019 22:38:51 +0300