Springdata_自己的小小总结01

ORM思想和JPA规范,hibernate实现JPA的测试,jpql语句的使用

jdbc的原始操作API

问题收集:
1、是通过实体类和数据库打交道的,那么实体类的属性的类型和数据库的类型怎么对应?
2、为什么不用Springdata JDBC?他和mybatis和Springdata JPA的区别?
3、有多少张表?就要建多少个类吗?
4、原JDBC操作数据库时的两个缺点是:1、操作繁琐。2、占位符赋值麻烦。
5、为什么要使用ORM?
答:因为使用类与表的映射,可以不关注SQL语句的情况下,进行对对象的操作就可以实现对数据库的操作。
6、sun公司为什么要提出ORM思想?
7、JPA(java persistence API)的实现框架hibernate 其中也使用了JDBC吗?
8、JPA是操作关系型数据库,JPA能不能操作非关系型数据库?
JDBC是操作关系型数据库的,能不能操作非关系型数据库?
9、只要是ORM框架,都遵循了JPA规范了吗?
10、mybatis和hibernate都支持哪些数据库?

静态代码块,动态代理和静态代理 ----->AOP

hibernate是一款可以操作大部分关系型数据库的dao层框架,而ORM也是基于关系型数据库提出来的。

一、ORM(Object Relational Mapping,简称ORM)思想是: 主要目的是通过类来操作数据库表,不再重点关注SQL语句;
要建立两个关系, 一:类和表的关系 二:类的属性名和表的字段名的关系
二、JPA(java persistence API)是基于ORM的一套规范,由抽象类和接口组成

Hibernate 、TopLink 都是对JPA的实现。mybatis没有实现JPA。但是他们都是ORM框架。

1)、mybatis(对JDBC进行了封装,是半自动ORM框架,没有实现JPA规范)。
2)、Hibernate (对JDBC进行了轻量级的封装,是全自动ORM框架,自动生成SQL语句。如果要定制SQL的话,需要学习HQL)

jpa操作的操作步骤

1.加载配置文件创建实体管理器工厂
Persisitence:静态方法(根据持久化单元名称创建实体管理器工厂)
createEntityMnagerFactory(持久化单元名称)
作用:创建实体管理器工厂

2.根据实体管理器工厂,创建实体管理器
EntityManagerFactory :获取EntityManager对象
方法:createEntityManager
* 内部维护的很多的内容
内部维护了数据库信息,
维护了缓存信息
维护了所有的实体管理器对象
再创建EntityManagerFactory的过程中会根据配置创建数据库表
* EntityManagerFactory的创建过程比较浪费资源
特点:线程安全的对象
多个线程访问同一个EntityManagerFactory不会有线程安全问题
* 如何解决EntityManagerFactory的创建过程浪费资源(耗时)的问题?
思路:创建一个公共的EntityManagerFactory的对象
* 静态代码块的形式创建EntityManagerFactory

3.创建事务对象,开启事务
EntityManager对象:实体类管理器
beginTransaction : 创建事务对象
presist : 保存
merge : 更新
remove : 删除
find/getRefrence : 根据id查询
Transaction 对象 : 事务
begin:开启事务
commit:提交事务
rollback:回滚
4.增删改查操作
5.提交事务
6.释放资源

import javax.persistence.*;
import java.io.Serializable;
/**
 * 所有的注解都是使用JPA的规范提供的注解,
 * 所以在导入注解包的时候,一定要导入javax.persistence下的
 *
 */
@Entity //声明实体类
@Table(name="cst_customer") //建立实体类和表的映射关系
public class Customer implements Serializable {
    /**
     * @GeneratedValue:配置主键的生成策略
     *      strategy
     *          GenerationType.IDENTITY:自增,mysql
     *              *底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
     *           GenerationType.SEQUENCE: 序列,Oracle
     *              *底层数据库必须支持序列
     *            GenerationType.TABLE:jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
     *            GenerationType.AUTO: 由程序自动的帮助我们选择主键生成策略
     */
    @Id//声明当前私有属性为主键
    @GeneratedValue(strategy= GenerationType.IDENTITY) //配置主键的生成策略
    @Column(name="cust_id") //指定和表中cust_id字段的映射关系
    private Long custId;

    @Column(name="cust_name") //指定和表中cust_name字段的映射关系
    private String dfdf;

    @Column(name="cust_source")//指定和表中cust_source字段的映射关系
    private String custSource;

    @Column(name="cust_industry")//指定和表中cust_industry字段的映射关系
    private String custIndustry;

    @Column(name="cust_level")//指定和表中cust_level字段的映射关系
    private String custLevel;

    @Column(name="cust_address")//指定和表中cust_address字段的映射关系
    private String custAddress;

    @Column(name="cust_phone")//指定和表中cust_phone字段的映射关系
    private String custPhone;

   getter和setter方法省略....
}
/**
 *JPA的实现hibernate的保存测试
/*
public class SaveTest01 {

    @Test
    public void test01() {
        //创建实体类工厂,借助persistence的静态方法获取
        //其中的参数传的是持久化单元的名称,需要jpa文件中指定的

        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
        //创建实体管理类
        EntityManager em = factory.createEntityManager();
        //获取事务对象
        EntityTransaction tx = em.getTransaction();
        //开启事务
        tx.begin();
        //创建实体类对象
        Customer c = new Customer();

        c.setDfdf("zzzzz");
        //执行保存
        em.persist(c);

        //提交事务
        tx.commit();
        //释放资源
        em.close();
        factory.close();
    }
}

resource–>META-INF–>persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <!--配置持久化单元
            name:持久化单元名称
            transaction-type:事务类型
                 RESOURCE_LOCAL:本地事务管理
                 JTA:分布式事务管理 -->
    <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
        <!--配置JPA规范的服务提供商 -->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <!-- 数据库驱动 -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <!-- 数据库地址 -->
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test" />
            <!-- 数据库用户名 -->
            <property name="javax.persistence.jdbc.user" value="root" />
            <!-- 数据库密码 -->
            <property name="javax.persistence.jdbc.password" value="root" />

            <!--jpa提供者的可选配置:我们的JPA规范的提供者为hibernate,所以jpa的核心配置中兼容hibernate的配 -->
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
        </properties>
    </persistence-unit>

</persistence>

pom.xml中的配置

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.hibernate.version>5.0.7.Final</project.hibernate.version>
    </properties>

    <dependencies>
        <!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>

        </dependency>

        <!-- hibernate对jpa的支持包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${project.hibernate.version}</version>
        </dependency>

        <!-- c3p0 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${project.hibernate.version}</version>
        </dependency>

        <!-- log日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!-- Mysql and MariaDB -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>

JPA的复杂查询(单表的复杂查询)
JPQL全称Java Persistence Query Language

基于首次在EJB2.0中引入的EJB查询语言(EJB
QL),Java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。

其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。
2.jpal语句
学JPQL记住两个点
2.1.JPQL和SQL很像,查询关键字都是一样的
2.唯一的区别是:JPQL是面向对象的
2.2. JPQL书写规则
JPA的查询语言,类似于sql
1.里面不能出现表名,列名,只能出现java的类名,属性名,区分大小写
2.出现的sql关键字是一样的意思,不区分大小写
3.不能写select * 要写select 别名

/**
     * 用find查询,根据主键查询
     */
    @Test
    public void test02() {
        //获得实体管理类
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Customer c = new Customer();
        //执行该方法的时候就发送SQL查询语句
        Customer customer = em.find(Customer.class, 1l);

//        System.out.println(customer);
        tx.commit();
        em.close();
//        不能关闭工厂实体管理类对象,因为下次访问的时候,不能获取到该对象,由于这个对象是由static修饰只运行一次,第二次
//        JPAUtil.close();
    }

    /**
     * 用reference查询,根据主键查询
     */
    @Test
    public void test03() {
        //获得实体管理类
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Customer c = new Customer();
        //该方法的SQL运行时机是在使用的时候发送查询,此处用了代理对象,如果
        //查不到内容的话,会报错。但是find方法就不会,会返回一个null
        //这也叫延迟加载或者懒加载,浪费系统性能,只有用到该对象时,才会发送SQL语句来查询
        Customer customer = em.getReference(Customer.class, 1l);
//        System.out.println(customer);
        tx.commit();
        em.close();
    }

    /**
     * 删除
     */
    @Test
    public void test04() {
        //获得实体管理类
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        Customer c = new Customer();
        //先查询出来
        Customer customer = em.find(Customer.class, 1l);
        //再删除
        em.remove(customer);
        tx.commit();
        em.close();
    }

    /**
     * 修改
     */
    @Test
    public void test05() {
        //获得实体管理类
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        //先查询出来
        Customer customer = em.find(Customer.class, 2l);
        //再修改
        customer.setDfdf("bbbb");
        em.merge(customer);
        tx.commit();
        em.close();
    }

复杂查询(单表的复杂查询)

    /**
     * 查询全部
     */
    @Test
    public void test06() {
        //获得实体管理类
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        String ql = "from Customer";
        Query query = em.createQuery(ql);
        List<Customer> resultList = query.getResultList();
        for (Customer customer : resultList) {
            System.out.println(customer);
        }
        tx.commit();
        em.close();
    }


    /**
     * 分页查询
     */
    @Test
    public void test07() {
        //获得实体管理类
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        String ql = "from Customer";
        Query query = em.createQuery(ql);
        //这里不用limit的原因是持久层框架为了通用性
        //设置起始索引 0不包括0
        query.setFirstResult(0);
        //设置每页显示的条数
        query.setMaxResults(2);
        List<Customer> resultList = query.getResultList();
        for (Customer customer : resultList) {
            System.out.println(customer);
        }
        tx.commit();
        em.close();
    }

    /**
     * 条件查询
     */
    @Test
    public void test08() {
        //获得实体管理类
        EntityManager em = JPAUtil.getEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        String ql = "from Customer where custLevel like '2%' ";
        Query query = em.createQuery(ql);
//        query.setParameter(1, "2%");
        Object sr = query.getSingleResult();
        System.out.println(sr);
        tx.commit();
        em.close();
    }

这是原始JDBC的操作关系型数据库的代码

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

/**
 * 这是原始JDBC的操作关系型数据库的代码
 * JDBC(Java Database Connectivity)是java提供的一套操作关系型									                     数据库的规范
 * 有以下问题:
 *  1、操作繁琐 ----------->用jdbc工具类
 *  2、占位符赋值麻烦------->
 *
 *
 *      内容在计算机中是以二进制的形式传输。
 *      举个例子:一个例子是:当连接数据库时,URL的后边加的characterEncoding=utf8作用是
 *  指定发送端和接收端的编码或解码格式,而传送途中是以二进制的形式传送;另外一个例子是:加载properties
 *  的文件时,
 */
public class InsertDemo {
    public static void main(String[] args) throws Exception {

        String sql = "INSERT INTO  USER (id,username,PASSWORD,NAME) VALUES(?,?,?,?);";
//        JDK8可以不加载驱动
//        String driver="com.mysql.jdbc.Driver";
//        Class.forName(driver);
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8","root","root");

        User user = new User();
        user.setUsername("wangwu");
        user.setPassword("123");
        user.setName("小小小小");
        user.setId(10);


        PreparedStatement pst = connection.prepareStatement(sql);
        pst.setInt(1,user.getId());
        pst.setString(2,user.getUsername());
        pst.setString(3,user.getPassword());
        pst.setString(4,user.getName());
        boolean execute = pst.execute();
        System.out.println(execute);

    }
}

数据库工具类的连接的代码如下,并使用了数据库连接池(druid)

数据库连接池的源码分析 https://www.cnblogs.com/wang-meng/p/5463020.html
其中的配置最小的连接数是连接池一直保持的连接数,最大的连接数是连接池超过最小的连接数后,会创建新的连接,但是用完不会关闭,会归还给连接池。可以创建最大限度的连接就是最大连接数,当超过最大连接数,他们会形成队列,排队等候。
数据库连接池有 Druid ,c3p0 等 静态代码块的详解,点击以下链接
https://blog.csdn.net/qq_35868412/article/details/89360250

prepareStatment利用占位符防止SQL注入的原理是:

不是拼接字符串,而是在字符串(“”)中加了一个单引号(‘’),这样就不会改变SQL语句的结构了。

import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/*
	1. 声明静态数据源成员变量
	2. 创建连接池对象
	3. 定义公有的得到数据源的方法
	4. 定义得到连接对象的方法
	5. 定义关闭资源的方法
 */
public class JDBCUtils {
	// 1.	声明静态数据源成员变量
	private static DataSource ds;

	// 2. 创建连接池对象
	static {
		// 加载配置文件中的数据
		InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
		Properties pp = new Properties();
		try {
			pp.load(is);
			// 创建连接池,使用配置文件中的参数
			ds = DruidDataSourceFactory.createDataSource(pp);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 3. 定义公有的得到数据源的方法
	public static DataSource getDataSource() {
		return ds;
	}

	// 4. 定义得到连接对象的方法
	public static Connection getConnection() throws SQLException {
		return ds.getConnection();
	}

	// 5.定义关闭资源的方法
	public static void close(Connection conn, Statement stmt, ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {}
		}

		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {}
		}

		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {}
		}
	}

	// 6.重载关闭方法
	public static void close(Connection conn, Statement stmt) {
		close(conn, stmt, null);
	}
}
发布了59 篇原创文章 · 获赞 1 · 访问量 754

猜你喜欢

转载自blog.csdn.net/weixin_43983411/article/details/103180698
今日推荐