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.