搭建第一个SpringDataJPA工程及基本操作

搭建第一个SpringDataJPA工程

1.创建Java工程

2.导入jar包或者maven坐标

<properties>
        <spring.version>4.2.4.RELEASE</spring.version>
        <hibernate.version>5.0.7.Final</hibernate.version>
        <slf4j.version>1.6.6</slf4j.version>
        <log4j.version>1.2.12</log4j.version>
        <c3p0.version>0.9.1.2</c3p0.version>
        <mysql.version>5.1.6</mysql.version>
    </properties>

    <dependencies>
        <!-- junit单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>

        <!-- spring beg -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- spring end -->

        <!-- hibernate beg -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.1.Final</version>
        </dependency>
        <!-- hibernate end -->

        <!-- c3p0 beg -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0.version}</version>
        </dependency>
        <!-- c3p0 end -->

        <!-- log end -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <!-- log end -->


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>1.9.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>

        <!-- el beg 使用spring data jpa 必须引入 -->
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>javax.el-api</artifactId>
            <version>2.2.4</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>javax.el</artifactId>
            <version>2.2.4</version>
        </dependency>
        <!-- el end -->
    </dependencies>

3.创建核心配置文件beans.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/data/jpa
		http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">


    <!--开启注解-->
    <context:annotation-config/>
    <!--开启组件扫描-->
    <context:component-scan base-package="com.zx"></context:component-scan>

    <!--开启切面注解-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>


    <!--配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa?useUnicode=true&amp;characterEncoding=UTF-8"></property>
        <property name="user" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>


    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="packagesToScan" value="com.zx.entity"></property>
        <!--底层Hibernate实现厂商-->
        <property name="persistenceProvider">
            <bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean>
        </property>

        <!--JPA的供应商适配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="generateDdl" value="true" />
                <property name="database" value="MYSQL" />
                <!--方言-->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
                <property name="showSql" value="true" />
            </bean>
        </property>
        <!--注入JPA的配置信息-->
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>


    </bean>


    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"></property>
    </bean>

    <jpa:repositories base-package="com.zx.dao" transaction-manager-ref="transactionManager" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>


    <!--aop相关XML配置-->
    <!--<bean id="myAspect_xml" class="com.zx.aop.MyAspect_XML"></bean>
    <aop:config>
        <aop:aspect id="myaspect" ref="myAspect_xml">
            <aop:pointcut id="pointcut" expression="execution(public * com.zx.service..*.*(..))"/>
            <aop:before method="test01" pointcut-ref="pointcut"></aop:before>
        </aop:aspect>
    </aop:config>-->
</beans>

4.创建实体类

/*
		@Entity  实体类映射
		@Table  映射的表格
			name  表格名称
		@Id     主键
		@GeneratedValue  主键生成策略
		
				IDENTITY  主键自动递增(适用于底层支持自动递增的数据库)
				SEQUENCE  序列(适用于Oracle)
				AUTO      自动创建第三张表维护主键的下一个值
				TABLE     创建第三张表维护主键的下一个值
		 */

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

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

5.创建dao层

/**
 * 创建符合SpringDataJPA规范的接口dao
 * JpaRepository<实体类类型,主键类型>:用来完成基本CRUD操作
 * JpaSpecificationExecutor<实体类类型>:用于复杂查询(分页等查询操作)
 */
public interface XXXDao extends JpaRepository<XXX,实体类中主键类型>, JpaSpecificationExecutor<XXX>

6.测试

Spring提供的单元测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class UserDaoTest {
    @Resource
    private UserDao userDao;
    @Test
    public void Test(){
        User user=new User("李四","45612563");
        userDao.save(user);
    }
    //删除
    @Test
    public void Test01(){
        //userDao.delete(5);
       User user=new User();
       user.setId(3);
        userDao.delete(user);
    }
     
}

7.基本增删改查操作

增加:save(对象)
		如果对象中没有id,则执行添加操作
		如果有id值,需要判断id在数据库中是否存在,如果不存在,则执行添加操作
													如果存在,则执行修改操作
	删除:delete(主键)
		  delete(带有数据库中存在的id的对象)
	修改:save(带有数据库中存在的id的对象)
	查询某一个:
		findOne(主键)   不管是否使用到对象,都会发送sql语句,及时加载
		getOne(主键)    什么时候使用对象,什么时候发送sql语句,懒加载
				直接使用对象报错no session问题
				解决办法:在方法上追加事务注解@Transactional

8.执行原理

通过jdk动态代理技术创建JpaRepository与JpaSpecificationExecutor子实现类SimpleJpaRepository在SimpleJpaRepository类中将findOne方法重写

9.查询机制

9.1查询某一个

​ findOne(主键) 不管是否使用到对象,都会发送sql语句,及时加载
​ getOne(主键) 什么时候使用对象,什么时候发送sql语句,懒加载
​ 直接使用对象报错no session问题
​ 解决办法:在方法上追加事务注解@Transactional
​ *findOne(动态条件Specification)

//查询
    @Test
    public void Test02(){
    
    
        List<User> list = userDao.findAll();
        System.out.println(list);
        User user = userDao.findOne(4);
        System.out.println(user);
    }
    @Test
    @Transactional
    public void Test03(){
    
    
        User user = userDao.getOne(4);
        System.out.println(user);
    }
9.2查询所有

​ findAll() 查询所有
​ findAll(排序Sort) 查询所有并排序

Sort sort = new Sort(Sort.Direction.DESC,"id");
List<User> users = userDao.findAll(sort);

​ findAll(分页) 查询所有并分页

Pageable pageable = new PageRequest(1,2);
Page<User> page = userDao.findAll(pageable);
System.out.println(page.getContent());
9.3JPQL查询

​ 使用JPQL语句查询所有 @Query(“JPQL语句”)

@Query("from User")
List<User> testAll();

@Query("from User where id=?1")
User testId(int id);
 
 @Query("from User where username=?1 and password=?2 ")
 User testUsernameAndPassword(String username,String password);    
9.4SQL查询
@Query(value = "select * from t_user",nativeQuery = true)
List<User> testAllSQL();

不管JPQL还是SQL,在@Query(“增删改语句”),但是需要追加@Modifying,在测试方法上标明事务注解以及不回滚注解@Transactional @Rollback(value = false)

@Query("delete from User where password=?")
    @Modifying
//通知Spring Data 这是一个DELETE或UPDATE操作。
    void deleteTest(String password);
@Test
    @Transactional
    @Rollback(value = false)
    public void test10(){
     userDao.deleteTest("123123");
    }    
9.5特殊方法命名查询

findBy开头+属性名称的首字母大写

User findByPasswordAndUsername(String password,String username);
9.6动态查询

findAll(动态条件Specification) 动态查询

//单条件动态查询   
@Test
    public void test12(){
        final Specification<User> spec=new Specification<User>(){

            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //获取要查询的字段
                Path<Object> username = root.get("username");
                //构造条件
                Predicate predicate = criteriaBuilder.equal(username, "admin");
                return predicate;
            }
        };
        List<User> list = userDao.findAll(spec);
        System.out.println(list);
    }
//多条件动态查询
@Test
public void test13(){
        final Specification<User> spec=new Specification<User>(){
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //获取要查询的字段
                Path<Object> username = root.get("username");
                Path<Object> password = root.get("password");
                //构造条件
                Predicate predicate1 = criteriaBuilder.equal(username, "admin");
                Predicate predicate2 = criteriaBuilder.equal(password, "456789");
                Predicate predicate = criteriaBuilder.and(predicate1, predicate2);
                return predicate;
            }
        };
        List<User> list = userDao.findAll(spec);
        System.out.println(list);
    }
//动态模糊查询
@Test
public void test14(){
     Specification<User> specification=new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Object> username = root.get("username");
                Predicate predicate = criteriaBuilder.like(username.as(String.class), "%adm%");
                return predicate;
            }
        };
        List<User> users = userDao.findAll(specification);
        System.out.println(users);
    }

findAll(动态条件Specification,分页) 动态查询并分页

Pageable pageable=new PageRequest(0,2);
Page<User> page = userDao.findAll(spec, pageable);
System.out.println(page.getContent());

findAll(动态条件Specification,排序) 动态查询并排序

    @Test
    public void test14(){
        Specification<User> specification=new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Object> username = root.get("username");
                Predicate predicate = criteriaBuilder.like(username.as(String.class), "%adm%");
                return predicate;
            }
        };
        Sort sort=new Sort(Sort.Direction.DESC,"id");
        List<User> users = userDao.findAll(specification,sort);
        System.out.println(users);
    }

10.关联对象

10.1多对一和一对多
/*
    @ManyToOne 多对一
        targetEntity 对方实体字节码
    @JoinColumn  添加外键
        name 外键名称
        referencedColumnName 外键引用方的名称
     */
    
    @Entity
@Table(name = "t_person")
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String username;
    private String password;
    @ManyToOne(targetEntity = Group.class)
    @JoinColumn(name = "gid",referencedColumnName = "id")
    private Group group;
/*
@OneToMany 一对多
    mappedBy 对方维护外键关系
 */
 @Entity
@Table(name = "T_group")
public class Group {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String gname;
    @OneToMany(mappedBy = "group")
    private List<Person> persons;
10.2测试过程

需要绑定外键关系,一般情况下,是多方设置一方需要先保存一(group)方,再保存多方
如果先保存多方,再保存一方的时候,需要追加事务注解以及关闭回滚操作

@Test
    @Transactional
    @Rollback(value = false)
    public void add(){
    
    
        Person person=new Person("admin","admin");
        Group group=new Group("一组");
        person.setGroup(group);//一方
        personDao.save(person);
        groupDao.save(group);
    }
级联添加
@OneToMany(mappedBy = "group",cascade = CascadeType.PERSIST)
    

	@Test
    public void test(){
        Person person=new Person("lisi","lisi");
        Person person1=new Person("zhangsan","zhangsan");
        Group group=new Group("二组");
        person.setGroup(group);
        person1.setGroup(group);
        List<Person> persons=new ArrayList<>();
        persons.add(person);
        persons.add(person1);
        group.setPersons(persons);
        groupDao.save(group);
    }
级联删除
@OneToMany(mappedBy = "group",cascade = CascadeType.REMOVE)

    @Test
    public void del(){
    
    
        groupDao.delete(1);
    }
级联更新
@OneToMany(mappedBy = "group",fetch = FetchType.EAGER,cascade = CascadeType.MERGE)
    @Test
    @Transactional
    @Rollback(value = false)
    public void update(){
        Group group=groupDao.findOne(4);
        List<Person> persons = group.getPersons();
        group.setGname("one");
        persons.get(0).setUsername("aaa");
        groupDao.save(group);
    }

级联查询

通过一方查询多方,会报错懒加载问题,解决办法:
方式一:追加事务@Transactional 发送两条sql语句

@Test
    @Transactional
    public void find(){
        Group group=groupDao.findOne(4);
        System.out.println(group);
        System.out.println(group.getPersons());
    }

​ 方式二:关闭懒加载或者开启及时加载(抓取策略)
​ @OneToMany(mappedBy = “group”,fetch = FetchType.EAGER) 发送一条sql语句

10.3多对多
/*
    @ManyToMany 多对多
        targetEntity  对方字节文件
    @JoinTable  加入中间表
        name 中间表名称
        joinColumns 本表在中间表中的配置
            @JoinColumn 配置外键
                name 外键名称
                referencedColumnName 外键引用方的名称
        inverseJoinColumns  对方表在中间表中的配置
            @JoinColumn 配置外键
                name 外键名称
                referencedColumnName 外键引用方的名称
     */

student

@Entity
@Table(name = "t_student")
public class Student {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int sid;
    private String sname;

    @ManyToMany(targetEntity = Teacher.class,fetch = FetchType.EAGER)
    @JoinTable(name = "t_student_teacher",
               joinColumns = {@JoinColumn(name = "sid",referencedColumnName = "sid")},
               inverseJoinColumns = {@JoinColumn(name="tid",referencedColumnName = 
                 "tid")})
    private List<Teacher> teachers;
    public Student() {
    }

teacher

@Entity
@Table(name = "t_teacher")
public class Teacher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int tid;
    private String tname;
    @ManyToMany(mappedBy = "teachers")
    private List<Student> students;

    public Teacher() {
    }

测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:beans.xml")
public class ManyToMany {
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private TeacherDao teacherDao;
    @Test
    public void add(){
        Student student1=new Student("张三");
        Student student2=new Student("李四");
        Teacher teacher=new Teacher("李老师");
        List<Teacher> teachers=new ArrayList<>();
        teachers.add(teacher);
        student1.setTeachers(teachers);
        student2.setTeachers(teachers);
        teacherDao.save(teacher);
        studentDao.save(student1);
        studentDao.save(student2);
    }

猜你喜欢

转载自blog.csdn.net/qq_45299673/article/details/119492834
今日推荐