Spring Data Jpa 学习笔记

Jpa (Hibernate) debug

设置以下属性为true:

hibernate.show_sql=true    //显示sql
hibernate.format_sql=true    //格式化显示的sql
hibernate.use_sql_comments=true    //显示sql注释,比如sql的执行方式:原生sql还是hql
hibernate.generate_statistics=true    //开启统计功能,比如统计sql执行时间,返回的数据条数

此外还需配置org.hibernate.stat包的日志级别为DEBUG, 如logback.xml配置为:

<logger name="org.hibernate.stat" level="DEBUG" />

这样,我们在执行sql之后可以看到如下输出:

DEBUG o.hibernate.stat.internal.ConcurrentStatisticsImpl - HHH000117: HQL: 执行的sql语句, time: 1000ms, rows: 10000

可以看到返回10000条数据,耗时1秒

Tips:

如果用JUnit的方式运行,需要将logback.xml文件放在目录src/test/resources下面,否则logback.xml的

修改不会生效,从而无法看到debug语句的输出.

2018-03-16

使用spring-data-jpa实现持久层时, jpa提供了基本的持久化接口类:CrudRepository, JpaRepository.
接口中有对数据进行事务操作的save方法,可以做单条和批量操作。但是这个save方法实现的是插入数据或
更新数据的操作。当我只需要插入数据或是只需要更新一条(批)数据时,就没有现成的接口。 这个时候
就需要自定义repository实现。

【详细请参考Spring Data JPA-reference 文档】
自定义repository实现有两种方式:
    方式一. 给单个repository创建自定义的repository实现;
    方式二. 创建可以被多个repository使用的repository实现;

方式一:

    示例1:

    

interface BatchRepository {
		public void update(Customer customer);
	}
	class CustomerRepositoryImpl implements BatchRepository {
		public void update(Customer customer) {
			...
		}
	}
	//修改主repository
	interface CustomerRepository extends CrudRepository<User, Long>, BatchRepository
	{
	// Declare query methods here
	}
Tips: 注意此处的实现类的类名必须是CustomerRepository + Impl, 就是说必须是主repository的名加上Impl,

        使用其他名字的话, 编译时会报错:No property 方法名(此处为update) found for type 实体类名(此处为Customer)

方式二: 【该方式的实现类的类名没有实现方式一的限制】

    示例二:

    

@NoRepositoryBean
	public interface BatchRepository<T, ID extends Serializable>
	extends Repository<T, ID> {
		void update(ID id);
	}
	public class BatchRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
		implements BatchRepository<T, ID> {	
		private final EntityManager entityManager;
		
		//必须添加此构造器
		public BatchRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
			super(entityInformation, entityManager);
			this.entityManager = entityManager;
		}

		@Transactional
		public List<T> update(List<T> list) {
			for(int i=0; i<list.size(); i++){
				//merge方法做数据更新, persist方法做数据插入, 具体请参考接口EntityManager
				entityManager.merge(list.get(i));
			}
			entityManager.flush();
			entityManager.clear();		
			
			return list;
		}
	}
	//在配置类中声明此自定义的repository实现, 否则编译时报错:No property 方法名(此处为update) found for type 实体类名(此处为Customer)
	@Configuration
	@EnableJpaRepositories(repositoryBaseClass = BatchRepositoryImpl.class)
	class ApplicationConfiguration { … }



2018-03-13

Tips:

    Entity类里面的字段可以不是主表的字段, 用@Column(name="xxx")与查询语句里面的字段名(或别名)映射就可以了,

    就像一个普通字段一样。

------------------------------------------------------------------------------------------------------------

1. 查询个别字段时(比如t.id, t.name, ...)易报Invalid column name(列名无效), 采用t.*的方式问题解决;

2. 采用@Id声明的字段,必须在查询出的结果集中具有唯一性;

否则,当被@Id声明的字段对应多条数据时,将会映射多条一样的数据到java类。

因此,当需要多个字段才能唯一确定一条数据的唯一性时,需要采用联合主键

联合主键的声明如下

step1: 创建一个联合主键类,该类采用注解类javax.persistence. Embeddable声明, 并且必须实现接口java.io. Serializable;包含对应的字段和其 getter/setter方法:
@Embeddable
public class SalesManPk implements Serializable{
        private static final long serialVersionUID = xxxxxxxxxxxxxL;
private long id;
private Date date;
public long getId(){return id;}
public void setId(long id){ this.id = id;}
public Date getDate(){return date;}
public void setDate(Date date){this.date = date;}
}

step2: 在与表映射的类里面引用该联合主键类和字段, 需要给字段添加getter/setter方法:
@Entity
@ IdClass(SalesManPk.class)
@Table(name = "t_sales_performance")
public class SalesPerformance {
@Id
@Column(name = "id")
private long id;
@Id
@Column(name = "date")
private Date date;
public long getId(){return id;}
public void setId(long id){ this.id = id;}
public Date getDate(){return date;}
public void setDate(Date date){this.date = date;}
/* 省略其他相关字段 */
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值