added JPAInsertClause

This commit is contained in:
Karsten Ludwig Hauser 2019-02-22 13:31:21 +01:00
parent 2bf234caf7
commit df84a39734
7 changed files with 387 additions and 0 deletions

View File

@ -16,6 +16,7 @@ package com.querydsl.jpa;
import com.querydsl.core.QueryFactory;
import com.querydsl.core.Tuple;
import com.querydsl.core.dml.DeleteClause;
import com.querydsl.core.dml.InsertClause;
import com.querydsl.core.dml.UpdateClause;
import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.Expression;
@ -117,4 +118,12 @@ public interface JPQLQueryFactory extends QueryFactory<JPQLQuery<?>> {
*/
UpdateClause<?> update(EntityPath<?> path);
/**
* Create a new INSERT clause
*
* @param path entity to insert to
* @return insert clause
*/
InsertClause<?> insert(EntityPath<?> path);
}

View File

@ -69,6 +69,8 @@ public class JPQLSerializer extends SerializerBase<JPQLSerializer> {
private static final String UPDATE = "update ";
private static final String INSERT = "insert into ";
private static final String WHERE = "\nwhere ";
private static final String WITH = " with ";
@ -258,6 +260,25 @@ public class JPQLSerializer extends SerializerBase<JPQLSerializer> {
}
}
public void serializeForInsert(QueryMetadata md, List<Path<?>> columns, SubQueryExpression<?> query) {
append(INSERT);
JoinExpression je = md.getJoins().get(0);
final EntityPath<?> pe = (EntityPath<?>) je.getTarget();
append(pe.toString());
//handleJoinTarget(je);
append(" (");
boolean first = true;
for (Path<?> path : columns) {
if (!first) {
append(", ");
}
handle(path);
first = false;
}
append(")\n");
serialize(query.getMetadata(), false, null);
}
public void serializeForUpdate(QueryMetadata md, Map<Path<?>, Expression<?>> updates) {
append(UPDATE);
handleJoinTarget(md.getJoins().get(0));

View File

@ -0,0 +1,163 @@
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.querydsl.jpa.hibernate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import com.google.common.collect.Maps;
import com.querydsl.core.JoinType;
import com.querydsl.core.dml.InsertClause;
import com.querydsl.core.dml.UpdateClause;
import com.querydsl.core.support.QueryMixin;
import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.SubQueryExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.HQLTemplates;
import com.querydsl.jpa.JPAQueryMixin;
import com.querydsl.jpa.JPQLSerializer;
import com.querydsl.jpa.JPQLTemplates;
import com.querydsl.jpa.impl.JPAInsertClause;
/**
* UpdateClause implementation for Hibernate
*
* @author tiwe
*
*/
public class HibernateInsertClause implements
InsertClause<HibernateInsertClause> {
private final QueryMixin<?> queryMixin = new JPAQueryMixin<Void>();
private final List<Path<?>> columns = new ArrayList<Path<?>>();
private SubQueryExpression<?> subQuery;
private final SessionHolder session;
private final JPQLTemplates templates;
private final Map<Path<?>,LockMode> lockModes = new HashMap<Path<?>,LockMode>();
public HibernateInsertClause(Session session, EntityPath<?> entity) {
this(new DefaultSessionHolder(session), entity, HQLTemplates.DEFAULT);
}
public HibernateInsertClause(StatelessSession session, EntityPath<?> entity) {
this(new StatelessSessionHolder(session), entity, HQLTemplates.DEFAULT);
}
public HibernateInsertClause(Session session, EntityPath<?> entity, JPQLTemplates templates) {
this(new DefaultSessionHolder(session), entity, templates);
}
public HibernateInsertClause(SessionHolder session, EntityPath<?> entity,
JPQLTemplates templates) {
this.session = session;
this.templates = templates;
queryMixin.addJoin(JoinType.DEFAULT, entity);
}
@Override
public long execute() {
JPQLSerializer serializer = new JPQLSerializer(templates, null);
serializer.serializeForInsert(queryMixin.getMetadata(), columns, subQuery);
Map<Object, String> constants = serializer.getConstantToLabel();
Query query = session.createQuery(serializer.toString());
for (Map.Entry<Path<?>, LockMode> entry : lockModes.entrySet()) {
query.setLockMode(entry.getKey().toString(), entry.getValue());
}
HibernateUtil.setConstants(query, constants, queryMixin.getMetadata().getParams());
return query.executeUpdate();
}
@Override
public HibernateInsertClause columns(Path<?>... columns)
{
this.columns.addAll(Arrays.asList(columns));
return this;
}
@Override
public HibernateInsertClause select(SubQueryExpression<?> sq)
{
subQuery = sq;
return this;
}
/**
* Set the lock mode for the given path.
* @return the current object
*/
@SuppressWarnings("unchecked")
public HibernateInsertClause setLockMode(Path<?> path, LockMode lockMode) {
lockModes.put(path, lockMode);
return this;
}
@Override
public String toString() {
JPQLSerializer serializer = new JPQLSerializer(templates, null);
serializer.serializeForInsert(queryMixin.getMetadata(), columns, subQuery);
return serializer.toString();
}
@Override
public boolean isEmpty() {
return columns.isEmpty();
}
@Override
public <T> HibernateInsertClause set(Path<T> path, T value)
{
// TODO Auto-generated method stub
return null;
}
@Override
public <T> HibernateInsertClause set(Path<T> path, Expression<? extends T> expression)
{
// TODO Auto-generated method stub
return null;
}
@Override
public <T> HibernateInsertClause setNull(Path<T> path)
{
// TODO Auto-generated method stub
return null;
}
@Override
public HibernateInsertClause values(Object... v)
{
// TODO Auto-generated method stub
return null;
}
}

View File

@ -114,6 +114,11 @@ public class HibernateQueryFactory implements JPQLQueryFactory {
public HibernateUpdateClause update(EntityPath<?> path) {
return new HibernateUpdateClause(session.get(), path, templates);
}
@Override
public HibernateInsertClause insert(EntityPath<?> path) {
return new HibernateInsertClause(session.get(), path, templates);
}
@Override
public HibernateQuery<?> query() {

View File

@ -0,0 +1,150 @@
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.querydsl.jpa.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.Query;
import com.google.common.collect.Maps;
import com.querydsl.core.JoinType;
import com.querydsl.core.dml.InsertClause;
import com.querydsl.core.dml.UpdateClause;
import com.querydsl.core.support.QueryMixin;
import com.querydsl.core.types.EntityPath;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.ParamExpression;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.SubQueryExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.JPAQueryMixin;
import com.querydsl.jpa.JPQLSerializer;
import com.querydsl.jpa.JPQLTemplates;
/**
* UpdateClause implementation for JPA
*
* @author tiwe
*
*/
public class JPAInsertClause implements InsertClause<JPAInsertClause> {
private final QueryMixin<?> queryMixin = new JPAQueryMixin<Void>();
private final List<Path<?>> columns = new ArrayList<Path<?>>();
private final List<Expression<?>> values = new ArrayList<Expression<?>>();
private final EntityManager entityManager;
private final JPQLTemplates templates;
private SubQueryExpression<?> subQuery;
@Nullable
private LockModeType lockMode;
public JPAInsertClause(EntityManager em, EntityPath<?> entity) {
this(em, entity, JPAProvider.getTemplates(em));
}
public JPAInsertClause(EntityManager em, EntityPath<?> entity, JPQLTemplates templates) {
this.entityManager = em;
this.templates = templates;
queryMixin.addJoin(JoinType.DEFAULT, entity);
}
@Override
public long execute() {
JPQLSerializer serializer = new JPQLSerializer(templates, entityManager);
serializer.serializeForInsert(queryMixin.getMetadata(), columns, subQuery);
Map<Object,String> constants = serializer.getConstantToLabel();
Query query = entityManager.createQuery(serializer.toString());
if (lockMode != null) {
query.setLockMode(lockMode);
}
JPAUtil.setConstants(query, constants, queryMixin.getMetadata().getParams());
return query.executeUpdate();
}
public JPAInsertClause setLockMode(LockModeType lockMode) {
this.lockMode = lockMode;
return this;
}
@Override
public String toString() {
JPQLSerializer serializer = new JPQLSerializer(templates, entityManager);
serializer.serializeForInsert(queryMixin.getMetadata(), columns, subQuery);
return serializer.toString();
}
@Override
public JPAInsertClause columns(Path<?>... columns)
{
this.columns.addAll(Arrays.asList(columns));
return this;
}
@Override
public JPAInsertClause select(SubQueryExpression<?> sq)
{
subQuery = sq;
return this;
}
@Override
public JPAInsertClause values(Object... v)
{
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isEmpty()
{
// TODO Auto-generated method stub
return false;
}
@Override
public <T> JPAInsertClause set(Path<T> path, T value)
{
// TODO Auto-generated method stub
return null;
}
@Override
public <T> JPAInsertClause set(Path<T> path, Expression<? extends T> expression)
{
// TODO Auto-generated method stub
return null;
}
@Override
public <T> JPAInsertClause setNull(Path<T> path)
{
// TODO Auto-generated method stub
return null;
}
}

View File

@ -130,6 +130,15 @@ public class JPAQueryFactory implements JPQLQueryFactory {
}
}
@Override
public JPAInsertClause insert(EntityPath<?> path) {
if (templates != null) {
return new JPAInsertClause(entityManager.get(), path, templates);
} else {
return new JPAInsertClause(entityManager.get(), path);
}
}
@Override
public JPAQuery<?> query() {
if (templates != null) {

View File

@ -29,6 +29,7 @@ import org.junit.Test;
import com.google.common.collect.Maps;
import com.querydsl.jpa.domain.QAnimal;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.querydsl.sql.SQLExpressions;
public class JPAQueryFactoryTest {
@ -135,4 +136,33 @@ public class JPAQueryFactoryTest {
EasyMock.verify(mock, factoryMock);
}
@Test
public void insert() {
assertNotNull(queryFactory.insert(QAnimal.animal));
}
@Test
public void insert2() {
queryFactory2.insert(QAnimal.animal)
.set(QAnimal.animal.birthdate, new Date());
}
@Test
public void insert3() {
EasyMock.expect(mock.getEntityManagerFactory()).andReturn(factoryMock);
EasyMock.expect(factoryMock.getProperties()).andReturn(properties);
EasyMock.expect(mock.getDelegate()).andReturn(mock).atLeastOnce();
EasyMock.replay(mock, factoryMock);
assertNotNull(queryFactory3.insert(QAnimal.animal));
EasyMock.verify(mock, factoryMock);
}
@Test
public void insert4() {
queryFactory.insert(QAnimal.animal).columns(QAnimal.animal.id, QAnimal.animal.birthdate)
.select(SQLExpressions.select(QAnimal.animal.id, QAnimal.animal.birthdate).from(QAnimal.animal));
}
}