Java 使用MySQL 总结
-
一、JDBC 连接 MySQL ,JDBC 是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问
-
下载 jar 包: JDBC driver for MySQL in MySQL Connectors
-
加载JDBC驱动程序
// 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机) // 成功加载后,会将Driver类的实例注册到DriverManager类中。 try { Class.forName("com.mysql.jdbc.Driver") ; }catch(ClassNotFoundException e){ System.out.println("找不到驱动程序类 ,加载驱动失败!"); e.printStackTrace() ; }
-
提供JDBC连接的URL , 创建数据库的连接
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf-8"; String username = "root" ; String password = "root" ; try{ Connection con = DriverManager.getConnection(url , username , password ) ; }catch(SQLException se){ System.out.println("数据库连接失败!"); se.printStackTrace() ; }
-
创建一个Statement , 执行SQL语句
// 执行静态SQL语句 Statement statement = con.createStatement(); // 执行动态SQL语句 PreparedStatement preparedStatement = con.prepareStatement(sql); // 执行数据库存储过程 CallableStatement callableStatement = con.prepareCall("{CALL demoSp(? , ?)}"); // 执行查询数据库的SQL语句 ResultSet resultSet = statement.executeQuery("SELECT * FROM ...") ; // 用于执行INSERT、UPDATE或 DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等 int rows = statement.executeUpdate("INSERT INTO ...") ; // 用于执行返回多个结果集、多个更新计数或二者组合的语句 boolean flag = statement.execute(String sql) ;
-
处理结果,关闭连接
int columnCount = resultSet.getMetaData().getColumnCount(); while(resultSet.next()){ String name = resultSet.getString("name") ; String pass = resultSet.getString(1) ; // 此方法比较高效 } try{ conn.close() ; }catch(SQLException e){ e.printStackTrace() ; }
-
-
二、 JdbcTemplate : 是Spring框架支持的ORM
-
JdbcTemplate 介绍
- Spring 对数据库的操作在jdbc上面做了深层次的封装,使用spring的注入功能,可以把DataSource注册到 JdbcTemplate 之中
- 需要引用jar 包 : spring-jdbc 和 spring-tx
-
SpringBoot 与 JdbcTemplates 集成 , Spring 中使用 JdbcTemplates
-
在pom文件引入spring-boot-starter-jdbc的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.29</version> </dependency>
-
在application.properties文件配置mysql的驱动类,数据库地址,数据库账号、密码信息
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=123456
-
Entity 类
public class Account { private int id ; private String name ; private double money; // ....省略了getter. setter }
-
Dao 层
public interface IAccountDAO { int add(Account account); int update(Account account); int delete(int id); Account findAccountById(int id); List<Account> findAccountList(); } @Repository public class AccountDaoImpl implements IAccountDAO { @Autowired private JdbcTemplate jdbcTemplate; @Override public int add(Account account) { return jdbcTemplate.update("insert into account(name, money) values(?, ?)", account.getName(),account.getMoney()); } @Override public int update(Account account) { return jdbcTemplate.update("UPDATE account SET NAME=?, money=? WHERE id=?", account.getName(),account.getMoney(),account.getId()); } @Override public int delete(int id) { return jdbcTemplate.update("DELETE from TABLE account where id=?",id); } @Override public Account findAccountById(int id) { List<Account> list = jdbcTemplate.query("select * from account where id = ?", new Object[]{id}, new BeanPropertyRowMapper(Account.class)); if(list!=null && list.size()>0){ Account account = list.get(0); return account; }else{ return null; } } @Override public List<Account> findAccountList() { List<Account> list = jdbcTemplate.query("select * from account", new Object[]{}, new BeanPropertyRowMapper(Account.class)); if(list!=null && list.size()>0){ return list; }else{ return null; } } }
-
-
-
三 、 Hiberante : 全自动的ORM,请使用 JPA
-
Hiberante 介绍
- 两个例子
- Spring 提供对 DAO 的支持 , DAO模式
- 所有的数据访问都通过DAO组件完成,DAO组件封装了数据库的增、删、改、查等原子操作。
- 业务逻辑组件依赖于DAO组件提供的数据库原子操作,完成业务逻辑的实现
- Spring 为实现DAO组件提供了许多工具类(就Hibernate而言,Spring提供了:HibernateTemplate , HibernateCallback 和 HibernateDaoSupport 3个类)
- 不适合Hiberante的场景
- 安全性要求,不让开发人员看到表结构
- 开发规范要求,必须以存储过程实现
- 性能要求,SQL语句需要经过高度优化
-
以声明的方式管理SessionFactory 实例,直接在配置文件中配置
- 一旦配置了SessionFactory Bean,它会随着应用的启动而加载,并可以充分利用容器的功能,将sessionFactory 注入到DAO组件中,一旦DAO获得了sessionFactory,就可以完成实际数据库操作
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> <!-- 加载实体类的映射文件位置及名称 --> <property name="mappingLocations" value="classpath:mapping/*.hbm.xml" /> </bean>
<!-- Hibernate的配置文件:hibernate.cfg.xml --> <hibernate-configuration> <session-factory> <!-- 配置Hibernate的基本属性 --> <!-- 1.数据源配置到IOC容器中 --> <!-- 2.关联的.hbm.xml也在IOC容器配置SessionFactory实例 --> <!-- 3.配置Hibernate的基本属性:方言,SQL显示及格式化,生成数据表的策略以及二级缓存 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <property name="hibernate.show_sql">true</property> <property name="hbm2ddl.auto">update</property> </session-factory> </hibernate-configuration>
-
使用 HibernateTemplate (模板)
- HibernateTemplate 将持久层访问模板化,它只需要引用SessionFactory,就可以执行持久化操作
public class PersonDaoImp implements PersonDao { // HibernateTemplate 提供很多方法来完成基本的操作,如:增删改查,分页等 // HibernateTemplate 维护Hibernate相关的Session对象 private HibernateTemplate ht = null; private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory){ this.sessionFactory = sessionFactory; } public HibernateTemplate getHibernateTemplate() { if (ht == null){ ht = new HibernateTemplate(this.sessionFactory); } return ht; } public Person get(Integer id) { return getHibernateTemplate().get(Person.class, id); } }
-
使用 HibernateCallback
- 为了解决 HibernateTemplate 灵活性不足的问题,HibernateTemplate 提供了一种更加灵活的方式来操作数据库,可以直接使用 Hibernate 的Session直接进行操作
public List findByPage(String hql, int offset, int pageSize){ // 这个 execute 方法需要一个 HibernateCallback 实例,通过这个callback实例可以完全使用Hibernate的操作方式 List list = getHibernateTemplate().execute(new HibernateCallback<List>() { @Override public List doInHibernate(Session session) throws HibernateException { List result = session.createQuery(hql).setFirstResult(offset).setMaxResults(pageSize).list(); return result; } }); return list; }
-
使用 HibernateDaoSupport
-
Spring 提供了大量的 xxxDaoSupport 类, 这些DAO支持类对于实现DAO组件大有帮助,因为它已经完成了大量的基础性工作
-
Spring为 Hibernate 提供了HibernateDaoSupport 支持类, 可以更方便的实现DAO组件
// HibernateDaoSupport类已经将 HibernateTemplate和 SessionFactory处理好了,子类可以直接使用 public class UserDaoImp extends HibernateDaoSupport implements UserDao { @Override public User get(Integer id) { return getHibernateTemplate().get(User.class, id); } }
-
-
-
四、JPA (Java Persistence API)
-
介绍 , 教程
- JPA 是一个ORM 规范,它本身不执行任何操作, 它需要一个实现。 像Hibernate,TopLink和iBatis这样的ORM工具实现了JPA 规范,可以从中任选一个
- Spring Data JPA 是Spring Data的子模块。使用Spring Data,使得基于“repositories”概念的JPA实现更简单和容易
- 如果应用程序面向 JPA编程,那么ORM框架就可以随意切换,因此具有更好的扩展性
- JPA @Id 和 @GeneratedValue 注解详解
- JPA与Hibernate的关系 , JPA 和 Mybatis 对比
-
Spring Boot 与 JPA 集成
-
添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
-
配置数据源和JPA
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver spring.datasource.url = jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC spring.datasource.username = root spring.datasource.password = root spring.datasource.tomcat.max-active=20 #连接哪种数据库 spring.jpa.database=mysql #查询过程中日志里是否显示查询语句 spring.jpa.show-sql=true #自动根据实体创建表 spring.jpa.hibernate.ddl-auto=update spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect spring.jpa.hibernate.naming.physical-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
-
创建实体类
@Entity @Table(name="person") @GenericGenerator(name="jpa-uuid",strategy="uuid") public class Person { @Id //@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(generator="jpa-uuid") @Column(length=32) private String id; @Column(name="name",nullable=true,length=20) private String name; @Column(name="age",nullable=true,length=4) private int age; // 省略 getter setter }
-
Dao 层
- 方法一:继承 JpaRepository , 可以极大的减少了JPA作为数据访问方案的代码量
public interface PersonRepository extends JpaRepository<Person, String>{ // JpaRepository 已经默认实现了一些基本的方法,如:findAll, findOne, save,delete 等 // 自定义 SQL 语句 @Query(value = "SELECT * FROM person WHERE name = ?1", nativeQuery = true) List<Person> findByPersonName(String person_name); }
- 方法二:使用JPA的EntityManager实现DAO
// 为所有DAO实现的基础层, 一个使用泛型的抽象类 public class BaseDao<T extends Serializable> { // 实体Class在子类的构造函数中赋值 private Class<T> clazz; // 使用 @PersistenceContext注解,可以获得 EntityManager实例,由PersistenceAnnotationBeanPostProcessor后处理器处理,从包中检索JPA实体管理器并注入它 @PersistenceContext EntityManager entityManager; public final void setClazz( Class< T > clazzToSet ){ this.clazz = clazzToSet; } public T findOne( long id ){ return entityManager.find( clazz, id ); } }
// 继承自 BaseDao,BaseDao为子类实现了大部分功能 @Repository public class FooDao extends BaseDao<Foo> implements IFooDao{ // 实体Class在构造函数中传递 public FooDao(){ setClazz(Foo.class ); } }
- 注意: 在 Spring 4.x 以前,可以使用 JpaTemplate ,这与Hibernate非常相似
-
Service 层,调用 Dao
@RestController @RequestMapping("/person") public class JPAController { @Autowired PersonRepository personRepository; @RequestMapping("/add") public String addPerson(Person person) { personRepository.save(person); return "success"; } @RequestMapping("/update") public String updatePerson(Person person) { personRepository.save(person); return "success"; } @RequestMapping("/del") public String delPerson(String id) { personRepository.deleteById(id); return "success"; } @RequestMapping("/findAll") public List<Person> findPerson() { return personRepository.findAll(); } }
-
-
-
五、MyBatis : 半自动的ORM,能够手写SQL,更加灵活
-
Spring Boot 集成 MyBatis(注解方式)
-
添加pom依赖
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.2.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency>
-
添加配置
spring.datasource.url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8 spring.datasource.username: root spring.datasource.password: 123456 spring.datasource.driver-class-name: com.mysql.jdbc.Driver
-
创建实体类
public class Person { private Integer id; private String name; private Integer age; // 忽略 getter setter }
-
创建 mapper
@Repository public interface UserMapper { @Select("SELECT * FROM Person WHERE id = #{id}") Person selectUser(int id); }
-
配置Mapper扫描,在启动类中添加MapperScan("")
@MapperScan("com.example.springmybatisdemo.mapper") //扫描的mapper @SpringBootApplication public class SpringmybatisdemoApplication { public static void main(String[] args) { SpringApplication.run(SpringmybatisdemoApplication.class, args); } }
-
创建服务
@Service public class UserService { @Autowired UserMapper userMapper; public Person selectUser(int id) { return userMapper.selectUser(id); } }
-
-
Spring Boot 与 mybatis 整合 非注解方式,用 mybatis-generator-gui 工具自动生成代码, github
-
除了mapper 不一样外,其他都一样
public interface UserMapper { void insertUser(User user); List<User> getUsers(); }
<!-- Mapper 配置文件, 可以使用 mybatis-generator-gui 自动生成--> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.sanfeng.springbootmybatisjpa.mapper.UserMapper"> <insert id="insertUser" parameterType="com.sanfeng.springbootmybatisjpa.beans.User"> insert into user values(#{id}, #{name}, #{score}) </insert> <select id="getUsers" resultType="com.sanfeng.springbootmybatisjpa.beans.User"> select * from user </select> </mapper>
-
-